C# 如何通过网络复制频繁使用的文件?
我需要通过网络复制一个大文件(大约20MB)。通常情况下,这不会是一个问题,但是,与文件位于同一个框中的应用程序相当频繁地(大约每秒一次)写入文件 因此,由于文件经常写入,C# 如何通过网络复制频繁使用的文件?,c#,.net,network-programming,C#,.net,Network Programming,我需要通过网络复制一个大文件(大约20MB)。通常情况下,这不会是一个问题,但是,与文件位于同一个框中的应用程序相当频繁地(大约每秒一次)写入文件 因此,由于文件经常写入,file.Copy调用经常失败。我还尝试了File.ReadAllLines,它似乎每次都能正常工作,但需要花费很长时间 有没有更好、更高效、更安全的方法通过网络复制文件 另外,该文件是由一个利用Log4Net的进程写入的。而且,如果有人想知道,写文件的过程不在我的掌握之中。您可以在打开文件时使用fileshare字段,以便在
file.Copy
调用经常失败。我还尝试了File.ReadAllLines
,它似乎每次都能正常工作,但需要花费很长时间
有没有更好、更高效、更安全的方法通过网络复制文件
另外,该文件是由一个利用Log4Net的进程写入的。而且,如果有人想知道,写文件的过程不在我的掌握之中。您可以在打开文件时使用fileshare字段,以便在访问文件时允许其他进程访问该文件,不幸的是,如果您的进程不是锁定文件的进程,那么您无法释放它,并且您已经提到,您无法更改正在编写的代码,通过在fileshare字段中允许r/w,您可以允许其他进程在复制文件时访问该文件。您可以编写一个小函数来检查文件是否被锁定,并更改代码,以便在文件被锁定时,您可以一直进行检查,直到它解锁,然后复制它。很可能是该文件。复制无法获得文件的独占锁 考虑到
File.Move
是一种快速操作,即使是在网络上。如果文件不需要在上一个应用程序中保留,则可以运行
for (int i = 0; i < 10; i++)
{
try {
File.Move(logFilePath, tempPathOnRemoteServer);
} catch (Exception) {
if (i == 9)
throw new Exception("Could not acquire lock");
System.Threading.Thread.Sleep(1000 * (i+1)); }
}
File.Copy(tempPathOnRemoteServer, endPathOnLocalHost);
for(int i=0;i<10;i++)
{
试一试{
Move(logFilePath,tempaphnremoteserver);
}捕获(例外){
如果(i==9)
抛出新异常(“无法获取锁”);
System.Threading.Thread.Sleep(1000*(i+1));}
}
Copy(tempPathnRemoteServer,endPathnLocalHost);
如果日志应用程序可以在文件打开时从移动的文件中恢复,则不会出现问题
或者,如果无法移动文件,请使用与上面相同的代码,将file.Move替换为file.Copy,但是,如果复制时间过长,您的独占锁可能会导致其他应用程序出现问题。使用FileStream类读取文件,不要忘记在重载构造函数中为FileAccess和FileShare设置适当的值
FileStream(String, FileMode, FileAccess, FileShare)
首先在本地制作一个副本怎么样?这将非常快,并且会保留副本的状态,然后上载副本,最后删除副本?如果您无法修改写入文件的程序,那么您的选项就有点有限。我想到的两种可能性是: 以独占方式打开文件,并在循环中复制:
using (var fin = File.Open(InputFilename, FileMode.Open, FileAccess.Read, FileShare.None))
{
using (var fout = File.OpenWrite(OutputFilename))`
{
int bytesRead = 0;
var buffer = new byte[65536];
while ((bytesRead = fin.Read(buffer, 0, buffer.Length)) > 0)
{
fout.Write(buffer, 0, bytesRead);
}
}
}
当您试图打开Log4Net文件进行读取时,如果Log4Net打开该文件进行写入,则必须编写代码来处理引发的异常。该代码应该稍等片刻,然后重试
这里潜在的缺点是,如果Log4Net无法写入文件(因为它是为独占访问而打开的),它可能会抛出异常。如果Log4Net不希望您以独占方式打开文件,那么
只需重命名文件,然后随意复制即可。如果在尝试重命名时Log4Net打开了该文件,那么代码将抛出异常。你可以再试一次。如果Log4Net在重命名文件后试图写入该文件,Log4Net将使用该名称创建一个新文件
我看不到任何其他选择
顺便说一下,20MB并不是一个大文件。在现代网络速度下,您应该能够在不到一秒钟的时间内复制它。您可以尝试这样处理它:
string pathToFile = "path-to-your-file" ;
using ( Stream s = File.Open( pathToFile , FileMode.Open , FileAccess.Read , FileShare.ReadWrite ) )
using ( TextReader r = new StreamReader( s ) )
{
string fileContents = r.ReadToEnd() ;
process( fileContents ) ;
}
如果写入文件的进程不愿意将其共享以供读取,那么您就是SOL
然而
.
.
.
你说:
另外,该文件是由一个利用Log4Net的进程写入的。
而且,如果有人想知道的话,写作的过程是我无法掌控的
您试图访问的文件是由Appender生成的,如或
如果是这样的话,默认的日志记录模型是FileAppender.ExclusiveLock
,它使用独占锁将文件保持在打开状态,但IIRC仍然愿意共享以供读取
但是获得所需结果(通过网络发送文件)的一种更简单的方法(为什么要重新发明轮子?)是使用。您可以向源应用程序Log4Net配置文件添加一个appender,这将对您有所帮助。您可以使用:
- “用于将事件传递到远程接收器。这是实现RemotingAppender.IRemoteLoggingSink接口的任何对象。它使用.NET远程处理传递事件。要将事件传递到的对象通过设置Appender接收器属性指定。”
- “接受套接字连接并将日志消息流回到客户端。输出以telnet友好的方式提供,以便可以通过TCP/IP套接字监控日志。这允许对应用程序日志进行简单的远程监控。 默认端口为23(telnet端口)。”
只是想一想。好的,那么,另一个选择就是总是模拟地写入两个文件。一吨