1

I'm trying to write out a Byte[] array representing a complete file to a file. This file may have a .csv or .db extension.

I have set up a synchronous client and server application based on MSDN Synchronous Sockets

After searching through S.O I discovered this (Can a Byte[] Array be written to a file in C#?) post which seems to indicate that it is possible to write a byte array to a file by using:

 File.WriteAllBytes(string path, byte[] bytes)

My problem is that this method seems to work for .csv files but not for .db files.

Why is this the case?

Some code below.

 //Client-side 
  public static void StartClient()
    {        
        byte[] bytes = new byte[9000];
        try
        {
            IPHostEntry ipHostInfo = Dns.GetHostEntry(Dns.GetHostName());
            IPAddress ipAddress = ipHostInfo.AddressList[0];
            IPEndPoint remoteEP = new IPEndPoint(ipAddress, 11000);
            Socket sender = new Socket(ipAddress.AddressFamily,
                SocketType.Stream, ProtocolType.Tcp);

            try
            {
                sender.Connect(remoteEP);
                byte[] msg= File.ReadAllBytes("CsvOrDbPath");
                int bytesSent = sender.Send(msg);
                int bytesRec = sender.Receive(bytes);
                sender.Shutdown(SocketShutdown.Both);
                sender.Close();
            }
            catch (ArgumentNullException ane) {
                Console.WriteLine("ArgumentNullException : {0}", ane.ToString());
            }
            catch (SocketException se) {
                Console.WriteLine("SocketException : {0}", se.ToString());
            }
            catch (Exception e)  {
                Console.WriteLine("Unexpected exception : {0}", e.ToString());
            }
        }
        catch (Exception e)
        {
            Console.WriteLine(e.ToString());
        }



//Server-side
    public static string data = null;
    public static void StartListening()
    {
        byte[] bytes = new byte[9000];
        IPHostEntry ipHostInfo = Dns.GetHostEntry(Dns.GetHostName());
        IPAddress ipAddress = ipHostInfo.AddressList[0];
        IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 11000);
        Socket listener = new Socket(ipAddress.AddressFamily,
            SocketType.Stream, ProtocolType.Tcp);
        try
        {
            listener.Bind(localEndPoint);
            listener.Listen(10);
            while (true)
            {
                Socket handler = listener.Accept();
                data = null;
                while (true)
                {
                    int bytesRec = handler.Receive(bytes);
                    int expecting = 8; //expected number of bytes
                    string path = "CSVorDbPath";

                    // Need to encode back into .db file format somehow
                    // Works for csv

                     File.WriteAllBytes(path, bytes);
                    break;
                }
                //Echo the data back to the client.
                //byte[] msg = Encoding.ASCII.GetBytes(data);
                //handler.Send(msg);
                handler.Shutdown(SocketShutdown.Both);
                handler.Close();
            }
        }
        catch (Exception e)
        {
            Console.WriteLine(e.ToString());
        }

When I use a .csv file this procedure works to an extent and I receive the same file on my server machine. When I use a .db file the procedure generates the .db file but it is not openable.

I suspect the issue is due to me not encoding the .db data into it's appropriate format - please can someone explain what is going on?

XOR
  • 407
  • 6
  • 16

1 Answers1

2

You are writing the whole 9000 byte buffer to the file. If the received file is smaller than that, it means that a bunch of 0 bytes are written to the file on disk as well. The software opening the CSV file probably doesn't care and discards that additional data, but the db format software is probably more rigorous.

Try to only write the received number of bytes to the file, e.g. using Linq:

File.WriteAllBytes(path, bytes.Take(bytesRec).ToArray());
Jens
  • 6,275
  • 2
  • 25
  • 51
  • 1
    If you don't want to write the entire contents of the array, I'd do `using (var file = File.Create("filename")) file.Write(bytes, 0, bytesRec);` to avoid making a pointless copy of the data. – Matthew Watson Sep 26 '19 at 08:59
  • I agree, there are somewhat smarter ways, but I wanted to keep the original idea. Worth noting though. – Jens Sep 26 '19 at 09:02
  • @Jens Thank you for your response. I am now only writing the received number of bytes to file which is a great improvement. Unfortunately, the .db file is still refusing to open. :( – XOR Sep 27 '19 at 08:16
  • @MatthewWatson Thank you, this is a good technique and an improvement, however the issue of the .db file not being openable remains. – XOR Sep 27 '19 at 08:18
  • @xor31four Compare your source file and the file written to your disk on a byte level, e.g. with a hex editor (you can use an online one such as https://hexed.it/ ). Also take note, that you may not have received the full data in a single read operation, as it dribbles in over time. It gets a bit complicated here, so first compare the files to see what is different. – Jens Sep 27 '19 at 08:28