【问题标题】:how to save a binary output of a Process and save it to file如何保存进程的二进制输出并将其保存到文件
【发布时间】:2019-09-23 11:39:39
【问题描述】:

我正在通过 Process 运行一个 exe 文件,它会生成二进制数据,我想将该数据保存到一个文件中。

在使用通常建议的方法(同步和异步)时,我遇到了几个障碍,希望您能帮助我。

我已经通过代码和提示符运行了命令,这是我的观察结果

1) 使用同步方法时,文件默认使用 UTF-8 编码(文件最终大于提示符 2)当将编码方法更改为 ASCII/默认时,编码似乎得到了正确处理,文件的大小似乎与提示符相似,不幸的是,旨在读取该文件的过程认为它“错误” 3) 使用 async 方法并使用 BinaryWriter 保存创建了一个看似准确的文件,但仍然无法通过输出读取。我相信我的错误可能是我如何附加“新行”

下面是我的异步方法代码。虽然同步一个在开始/停止之间只有“Output.ReadToEnd()”。

代码:

        private void createOCTree()
    {
        //Create process
        var cmd = @"oconv.exe";                         //OUTPUT IS C++ binary
        var arguments = @" C:\RadianceGeometry.rad";
        var outputFile = @"C:\test.oct";
        var workingDir = m_FileData.TemporaryFilesFolder;

        ProcessStartInfo cmdStartInfo = new ProcessStartInfo();
        cmdStartInfo.RedirectStandardInput = false;
        cmdStartInfo.RedirectStandardError = false;
        cmdStartInfo.RedirectStandardOutput = true;
        cmdStartInfo.UseShellExecute = false;
        cmdStartInfo.CreateNoWindow = true;
        cmdStartInfo.FileName = cmd;                    ////file name
        cmdStartInfo.Arguments = arguments;             ////arguments
        cmdStartInfo.WorkingDirectory = @"C:\";         ////working dir

        using (StreamWriter writer = new StreamWriter("C:\\testStream.oct"))
        {
        }

        var process = new Process();
        process.StartInfo = cmdStartInfo;

        process.OutputDataReceived += new DataReceivedEventHandler(OutputHandler);
        process.Start();
        process.BeginOutputReadLine();
        process.WaitForExit();
    }

    private void OutputHandler(object sendingProcess, DataReceivedEventArgs outLine)
    {
        try
        {
            byte[] bytes = Encoding.Default.GetBytes(outLine.Data);
            byte[] newLine = Encoding.Default.GetBytes("\n");                       
            AppendData("C:\\testStream.oct", bytes);
            AppendData("C:\\testStream.oct", newLine);     ////otherwise all is in one line     
        }
        catch { }   ////possibly last line is not properly handled
    }

    private static void AppendData(string filename, byte[] bits)
    {
        using (var fileStream = new FileStream(filename, FileMode.Append, FileAccess.Write, FileShare.None))
        using (var bw = new BinaryWriter(fileStream))
        {
            bw.Write(bits);
        }
    }

我的怀疑是我的“Try/Catch”遗漏了一些东西,或者换行符应该以不同的方式解析。 将所有路径设置为 c:\ 只是为了使其更易于阅读(而不是使用变量或实际路径)。

编辑:添加;我注意到在将提示输出与代码中的输出进行比较时,它们是相同的,除了某些行“输出”的第一个字符是“?”而不是工作文件中的随机“字形”。

编辑:添加了比较屏幕截图。 代码对比:

带换行符:https://ibb.co/HpztQ0Q

没有换行符:https://ibb.co/Lvcr9pH

【问题讨论】:

  • 二进制数据中没有行。检查源和目标的文件大小以查看它们是否相同。使用 Beyond Compare 将有助于确定差异发生在哪里。从不,从不,从不对二进制数据使用编码,它会破坏数据。编码会改变和删除字符。甚至 UTF8 也会改变字符 0x80。只需使用 BinaryWriter 节省蒸汽。
  • 感谢您的回复。我第一次尝试没有换行,但使用NL时输出似乎更符合提示结果。使用新行ibb.co/HpztQ0Q 不使用新行ibb.co/Lvcr9pH 代码不同之处在于某些地方的位被替换为“?”,我不知道该怎么办。
  • 您不能在二进制文件中使用换行符。使用 List 然后 AddRange 追加数据。
  • 用列表试过了,但没有太大区别; ibb.co/Pmh1GG7(注意与“正常”文件相比多出 156 个字节)
  • 对于二进制,任何差异(即使是一个字符)都是一个问题。检查差异是接收数据还是仅写入。

标签: c# asynchronous process binary output


【解决方案1】:

我让它工作的方式是使用 cmd 作为命令,并且 在参数字段中,我使用了 /c" 标志,如下所述:What does cmd /C mean?

    String exeFileName = @"cmd.exe";
    String Arguments = @"/c oconv.exe C:\test\radgeom.rad > c:\test\scene.oct"; 

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-12-29
    • 1970-01-01
    • 2020-04-08
    • 2021-11-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-24
    相关资源
    最近更新 更多