将System.IO.Pipelines与Stream结合使用

时间:2018-12-16 11:10:06

标签: c# stream pipeline

我考虑在我们的应用程序中使用System.IO.Pipelines替换基于Stream的IO,以避免不必要的内存分配(首先考虑RecyclableMemoryStream,但似乎已经停产了)。但是在某些地方,由于外部库施加的接口,我仍然必须使用Stream。因此,我的PipeWriter需要将其数据包装在Stream中。

我在这个主题上没有找到太多内容,但是找到了在另一个问题的答案中使用装饰器模式(C# Stream Pipe (Stream Spy))的建议。我不确定将管道隐藏在Stream包装器后面是否是正确的选择,但找不到其他可以将数据通过管道传输到流的内容。我想念什么吗?

更新。这是一个使用SSH.NET开源库将文件上传到FTP服务器(https://gist.github.com/DavidDeSloovere/96f3a827b54f20d52bcfda4fe7a16a0b)的示例:

apply plugin: 'com.android.application'

android {
    compileSdkVersion 27
    defaultConfig {
        applicationId "com.my.example"
        minSdkVersion 21
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        multiDexEnabled true
        targetSdkVersion 27
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    productFlavors {
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:27.1.1'
    implementation 'com.android.support:design:27.1.1'
    implementation 'junit:junit:4.12'
    implementation 'com.android.support.test.espresso:espresso-core:3.0.2'
    androidTestImplementation 'com.android.support.test:rules:1.0.2'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    implementation 'postgresql:postgresql:9.0-801.jdbc4'
    implementation files('libs/numbers-lib.jar')
}

请注意,我们打开FileStream读取文件,然后将Stream引用传递给SftpClient。我可以在此处使用System.IO.Pipelines减少内存分配吗?我仍然需要为SftpClient提供一个Stream。

2 个答案:

答案 0 :(得分:6)

免责声明:我不是专家,只是拼凑起来...


答案(截至2019年1月)似乎是:对此没有官方支持。

System.IO.Pipelines主要是为networking use cases创建的。实际上,2.1中发布的管道代码具有no support for any endpoints

  

在这里,我们需要一些警告和免责声明:.NET Core 2.1中发布的管道不包含任何端点实现。

通用流适配器有一个proposed design for an API,但这是.NET Core 3.0里程碑的一部分。

甚至seems to be some reticence都可以实现基于文件的管道访问(也相当于FileStream管道)。这尤其令人失望,因为我也希望管道支持文件I / O。

我认为目前最好的选择是使用https://github.com/AArnott/Nerdbank.Streams中的UsePipe()方法


更新:这是我刚刚发现的另一个示例https://github.com/tulis/system-io-pipelines-demo/tree/master/src/SystemIoPipelinesDemo/SystemIoPipelinesDemo


更新:我可以制作基于管道的文件阅读器。您可以在这里阅读所有内容:https://github.com/atruskie/Pipelines.File.Unofficial

从性能的角度来看,基本上,使用Nerdbank.Streams这样的管道流适配器是一个不错的选择!

答案 1 :(得分:2)

现在似乎是利用 PipeReader 的 AsStream() 扩展的一种方式:

using (var fileStream = new FileStream(uploadfile, FileMode.Open))
    {
        Console.WriteLine("Uploading {0} ({1:N0} bytes)", uploadfile, fileStream.Length);
        client.BufferSize = 4 * 1024; // bypass Payload error large files
        var pipeReader = PipeReader.Create(fileStream);
        client.UploadFile(pipeReader.AsStream(), Path.GetFileName(uploadfile));
    }