Read and write in c#

980 Views Asked by At

I want to read a file(image) and another file video in c# and save(write) all the contents of both files(1 after another) in single txt file.Now i want to again retrieve the first image file content and second file content separately. Is it possible to read video and image file for save in single file.

3

There are 3 best solutions below

0
On

Short answer: Yes, it is possible.

Long answer: That depends heavily on your implementation.

You may, for example, create a holder class that receives both binaries as properties, serialize them and commit to storage; whenever necessary, you just load up the file and deserialize it back to an instance of the holder class.

0
On

Sure...

Assume two input streams infile1 and infile2 with one output stream outfile1. We will specify our file format to be {Infile 1 Length in 8 bytes},{Infile 2 Length in 8 bytes},{Infile 1 data},{Infile 2 data}

public static void Main(string[] args)
{
    using (Stream infile1 = File.Open("Foobar.jpg", FileMode.Open, FileAccess.Read, FileShare.Read))
    using (Stream infile2 = File.Open("Foobar.avi", FileMode.Open, FileAccess.Read, FileShare.Read))
    using (Stream outfile = File.Open("Out.bin", FileMode.Create, FileAccess.Write, FileShare.None))
    {
        // write lengths
        byte[] file1Len = BitConverter.GetBytes(infile1.Length);
        byte[] file2Len = BitConverter.GetBytes(infile2.Length);

        outfile.Write(file1Len, 0, 8);
        outfile.Write(file2Len, 0, 8);

        // write data
        infile1.CopyTo(outfile);
        infile2.CopyTo(outfile);
    }

    // read file 1
    using (Stream combinedFile = File.Open("out.bin", FileMode.Open, FileAccess.Read, FileShare.Read))
    {
        byte[] file1len = new byte[8];
        combinedFile.Read(file1len, 0, 8);
        long lFile1Len = BitConverter.ToInt64(file1len, 0);

        // advance past header
        combinedFile.Position = 16;

        // limit
        var limStream = new LimitedStream(combinedFile, lFile1Len);

        // use the file as normal
        var bmp = System.Drawing.Bitmap.FromStream(limStream);
        bmp.Save(@"C:\drop\demo.jpg");
    }

    // read file 2
    using (Stream combinedFile = File.Open("out.bin", FileMode.Open, FileAccess.Read, FileShare.Read))
    {
        byte[] file1len = new byte[8];
        combinedFile.Read(file1len, 0, 8);
        long lFile1Len = BitConverter.ToInt64(file1len, 0);

        byte[] file2len = new byte[8];
        combinedFile.Read(file2len, 0, 8);
        long lFile2Len = BitConverter.ToInt64(file2len, 0);

        // advance past header and first file
        combinedFile.Position = 16 + lFile1Len;

        // limit
        var limStream = new LimitedStream(combinedFile, lFile2Len);

        // copy video out
        var tempPath = System.IO.Path.GetTempFileName();
        using (Stream outStr = File.Open(tempPath, FileMode.Create, FileAccess.Write, FileShare.None))
        {
            limStream.CopyTo(outStr);
        }
    }
}

public class LimitedStream : Stream
{
    long StartPosition = 0;
    long FunctionalLength = 0;
    long EndPosition { get { return StartPosition + FunctionalLength; } }
    Stream BaseStream = null;

    public LimitedStream(Stream baseStream, long length)
    {
        StartPosition = baseStream.Position;
        FunctionalLength = length;
        BaseStream = baseStream;
    }

    public override bool CanRead
    {
        get { return true; }
    }

    public override bool CanSeek
    {
        get { return BaseStream.CanSeek; }
    }

    public override bool CanWrite
    {
        get { return false; }
    }

    public override void Flush()
    {
        BaseStream.Flush();
    }

    public override long Length
    {
        get { return FunctionalLength; }
    }

    public override long Position
    {
        get
        {
            return BaseStream.Position - StartPosition;
        }
        set
        {
            BaseStream.Position = value + StartPosition;
        }
    }

    public override int Read(byte[] buffer, int offset, int count)
    {
        if (BaseStream.Position + count > EndPosition)
            count = (int)(EndPosition - BaseStream.Position);
        // if there is no more data, return no read
        if (count < 1)
            return 0;

        return BaseStream.Read(buffer, offset, count);
    }

    public override long Seek(long offset, SeekOrigin origin)
    {
        if (origin == SeekOrigin.Current)
            return BaseStream.Seek(offset, origin);
        else if (origin == SeekOrigin.Begin)
            return BaseStream.Seek(offset - StartPosition, origin);
        else if (origin == SeekOrigin.End)
            return BaseStream.Seek(BaseStream.Length - EndPosition + offset, origin);
        else throw new NotSupportedException();
    }

    public override void SetLength(long value)
    {
        throw new NotSupportedException();
    }

    public override void Write(byte[] buffer, int offset, int count)
    {
        throw new NotSupportedException();
    }
}
0
On

I would recommend you to read files in bytes, structure the content and save them:

var FileOne = File.ReadAllBytes(URL).ToList().Select(x=> Convert.ToInt16(x)).ToList();
var FileTwo = File.ReadAllBytes(URL).ToList().Select(x=> Convert.ToInt16(x)).ToList();;

Now

StreamWriter SW = new StreamWriter (URL);
//To structure FileOne
FileOne.ForEach(x=> SW.Write("$(1)"+x+","));
//To structure FileTwo
FileOne.ForEach(x=> SW.Write("$(2)"+x+","));
SW.Close();

Please note that for restoring the saved file you have to convert it back to byte mode.

To do this you can split the (',') and start by reading each section, this can be done like this. ( This cant be the best solution but it works pretty fast )

var Restore = File.ReadAllText(URL).Split(',').ToList();
foreach(var i in Restore) {
    if (i.StartsWith("$(1)") {i.Replce("$(1)",""); and Do what you want}
    else if (i.StartsWith("$(2)") {i.Replce("$(2)",""); andDo what you want}
}

Don't forget to convert the string back to byte!!

.Select(x=> Convert.ToByte(x)).ToList();