【问题标题】:C# Prepend 40 bytes onto streamC# 在流中添加 40 个字节
【发布时间】:2013-12-13 10:51:44
【问题描述】:

我正在尝试发送文件的 FileStream。

但我现在想在开头添加 40 字节的校验和。

我该怎么做?我尝试创建自己的流类来连接两个流。我还研究了流编写器。

当然,它们一定是一种简单的方法。或者另一种方式。而且我不想将整个文件加载到一个字节数组中,追加到那个并将它写回一个流中。

public Stream getFile(String basePath, String path) {
    return new FileStream(basePath + path, FileMode.Open, FileAccess.Read);
 }

【问题讨论】:

    标签: c# wcf rest stream prepend


    【解决方案1】:

    MergeStream.cs。使用方法如下:

    var mergeStream = new MergeStream(new MemoryStream(checksum), File.OpenRead(path));
    return mergeStream;
    

    【讨论】:

    • 这实际上和我之前所做的一样,只是我不知道如何处理缺少的抽象方法。又名NotSupportedException()。谢谢:)
    • 投掷NSE 对流很好。 MergeStream 是只读的,所以你可以在 Write 中做的唯一明智的方法是告诉调用者“嘿,我不支持写作!”
    【解决方案2】:
    byte[] checksum = new byte[40];
    //...
    FileStream oldFileStream = new FileStream(oldFile, FileMode.Open, FileAccess.Read);
    FileStream newFileStream = new FileStream(newFile, FileMode.Create, FileAccess.Write);
    
    using(oldFileStream)
    using(newFileStream)
    {
        newFileStream.Write(checksum, 0, checksum.Length);
        oldFileStream.CopyTo(newFileStream);
    }
    File.Copy(newFile, oldFile, overwrite : true);
    

    如果不想使用临时文件,唯一的解决办法就是以ReadWrite模式打开文件并使用两个交替缓冲区:

    private static void Swap<T>(ref T obj1, ref T obj2) 
    {
        T tmp = obj1;
        obj1 = obj2;
        obj2 = tmp;
    }
    
    public static void PrependToFile(string filename, byte[] bytes)
    {
        FileStream stream = new FileStream(filename, FileMode.Open, FileAccess.ReadWrite);
        PrependToStream(stream, bytes);
    }
    public static void PrependToStream(Stream stream, byte[] bytes) 
    {
        const int MAX_BUFFER_SIZE = 4096;
        using(stream)
        {
            int bufferSize = Math.Max(MAX_BUFFER_SIZE, bytes.Length);
            byte[] buffer1 = new byte[bufferSize];
            byte[] buffer2 = new byte[bufferSize];
            int readCount1; 
            int readCount2;
    
            long totalLength = stream.Length + bytes.Length;
    
            readCount1 = stream.Read(buffer1, 0, bytes.Length);
            stream.Position = 0;
            stream.Write(bytes, 0, bytes.Length);
            int written = bytes.Length;
    
            while (written < totalLength)
            {
                readCount2 = stream.Read(buffer2, 0, buffer2.Length);
                stream.Position -= readCount2;
                stream.Write(buffer1, 0, readCount1);
    
                written += readCount1;
    
                Swap(ref buffer1, ref buffer2);
                Swap(ref readCount1, ref readCount2);
            }
        }
    }
    

    【讨论】:

    • @Doomsknight,是的,但它不会将整个文件加载到字节数组中,这是 OP 害怕的 =D
    • @Sinatr 虽然我知道他避免了这种情况,但我不同意克隆 8GB 文件只是为了在前面添加 40 个字节是一个有效的解决方案。
    猜你喜欢
    • 1970-01-01
    • 2012-10-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多