使用 NCopy/追加最新可用字节复制波形文件
本文关键字:字节 复制 波形 文件 NCopy 追加 最新 使用 | 更新日期: 2023-09-27 18:34:06
我有一个活动波记录wave-file.wav
发生在Source
文件夹中。我需要将此文件复制到具有新名称wave-file-copy.wav
Destination
文件夹。
记录和复制应并行进行。我已经实现了一个计划作业,它将每 10 分钟运行一次并将source
文件复制到 destination
.
private static void CopyWaveFile(string destinationFile, string sourceFile){
using (var fs = File.Open(sourceFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)){
using (var reader = new WaveFileReader(fs)){
using (var writer = new WaveFileWriter(destinationFile, reader.WaveFormat)){
reader.Position = 0;
var endPos = (int)reader.Length;
var buffer = new byte[1024];
while (reader.Position < endPos){
var bytesRequired = (int)(endPos - reader.Position);
if (bytesRequired <= 0) continue;
var bytesToRead = Math.Min(bytesRequired, buffer.Length);
var bytesRead = reader.Read(buffer, 0, bytesToRead);
if (bytesRead > 0){
writer.Write(buffer, 0, bytesRead);
}
}
}
}
}
}
即使源文件不断更新,复制操作工作正常。
复制操作所花费的时间呈线性时间增加,因为我每次都在复制整个文件。
我正在尝试实现一个新的函数ConcatenateWavFiles()
,它应该使用源记录的最新可用字节更新目标文件的内容。
我尝试了一些示例代码 - 我使用的方法是:
- 读取目标文件元信息,并获取长度。
- 将目标文件的
length
设置为源文件waveReader
的reader.Position
从位置开始读取源文件直到结束。
public static void ConcatenateWavFiles(string destinationFile, string sourceFile){ WaveFileWriter waveFileWriter = null; var sourceReadOffset = GetWaveFileSize(destinationFile); try{ using (var fs = File.Open(sourceFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { using (var reader = new WaveFileReader(fs)) { waveFileWriter = new WaveFileWriter(destinationFile, reader.WaveFormat); if (!reader.WaveFormat.Equals(waveFileWriter.WaveFormat)){ throw new InvalidOperationException( "Can't append WAV Files that don't share the same format"); } var startPos = sourceReadOffset - sourceReadOffset % reader.WaveFormat.BlockAlign; var endPos = (int) reader.Length; reader.Position = startPos; var bytesRequired = (int)(endPos - reader.Position); var buffer = new byte[bytesRequired]; if (bytesRequired > 0) { var bytesToRead = Math.Min(bytesRequired, buffer.Length); var bytesRead = reader.Read(buffer, 0, bytesToRead); if (bytesRead > 0) { waveFileWriter.Write(buffer, startPos, bytesRead); } } } } } finally{ if (waveFileWriter != null){ waveFileWriter.Dispose(); } } }
我能够获得新内容。
是否可以将最新内容附加到现有目标文件?
如果可能的话,我在代码中做错了什么?
我的代码抛出以下异常 - Offset and length were out of bounds for the array or count is greater than the number of elements from index to the end of the source collection.
我找不到使用 NAudio 库进行波形音频文件复制的解决方案。
但是我已经使用 C# MemoryStreams 和 FileStreams 实现了一个解决方案。
- 如果目标文件
- 不存在,请将源文件复制到目标。
- 将所有最新字节(在上次操作后记录(追加到目标文件。
- 修改波形文件标头以反映最后追加的字节。(否则不会更新文件的持续时间,只会增加文件大小。
定期重复此追加操作。
public void ReplicateFile(string destinationFile, string sourceFile){ if (!Directory.Exists(GetRoutePathFromFile(sourceFile))) return; if (!File.Exists(sourceFile)) return; if (Directory.Exists(GetRoutePathFromFile(destinationFile))){ if (File.Exists(destinationFile)){ UpdateLatestWaveFileContent(destinationFile, sourceFile); }else{ CopyWaveFile(destinationFile, sourceFile); } }else{ Directory.CreateDirectory(GetRoutePathFromFile(destinationFile)); CopyWaveFile(destinationFile, sourceFile); } } private static string GetRoutePathFromFile(string file){ var rootPath = Directory.GetParent(file); return rootPath.FullName; } private static void CopyWaveFile(string destination, string source){ var sourceMemoryStream = new MemoryStream(); using (var fs = File.Open(source, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)){ fs.CopyTo(sourceMemoryStream); } using (var fs = new FileStream(destination, FileMode.CreateNew, FileAccess.ReadWrite, FileShare.ReadWrite)){ sourceMemoryStream.WriteTo(fs); } } private static void UpdateLatestWaveFileContent(string destinationFile, string sourceFile){ var sourceMemoryStream = new MemoryStream(); long offset = 0; using (var fs = File.Open(destinationFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)){ offset = fs.Length; } using (var fs = File.Open(sourceFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)){ fs.CopyTo(sourceMemoryStream); } var length = sourceMemoryStream.Length - offset; var buffer = sourceMemoryStream.GetBuffer(); using (var fs = new FileStream(destinationFile, FileMode.Append, FileAccess.Write, FileShare.ReadWrite)){ fs.Write(buffer, (int)offset, (int)length); } var bytes = new byte[45]; for (var i = 0; i < 45; i++){ bytes[i] = buffer[i]; } ModifyHeaderDataLength(destinationFile, 0, bytes); } private static void ModifyHeaderDataLength(string filename, int position, byte[] data){ using (Stream stream = File.Open(filename, FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite)) { stream.Position = position; stream.Write(data, 0, data.Length); } }
尝试在源文件的实际结束之前读取源文件一两个 Wav 块。
情况可能是代码判断源文件的结尾太近而无法舒适。