流文件、正在使用的文件、FileSystemWatcher 和有关线程的问题

问题描述 投票:0回答:2

我一直在尝试创建一个脚本,该脚本获取文本文件的内容,可能如下所示(

.txt.
文件中的1行文本):

SomeData     SomeData     SomeData

这些文件会随机放入一个文件夹中。有时10个,有时1个。然后,大约每十分钟就会使用 robocopy 将文件从该文件夹移动到另一个文件夹。

无论如何,我想读取每个文件的单行文本并插入到数据库中。

工作正常一两次,但后来我得到文件正在使用错误。

尝试从

File.ReadAllText(textFile)
切换到
FileStream
,但仍然遇到同样的问题。

有人可以帮忙吗?

另外,我有点担心当放到服务器上时可能使用的线程数量。我可以在 Visual Studio Code 中看到线程,但有兴趣知道我可以做些什么来改进我的脚本并使其更高效?

我是编码新手!这将是我的第一次。

using System;
using System.IO;
using System.Data.SqlClient;


namespace IDGFileSystemWatcher
{
    class Program
    {
        static void Main(string[] args)
        {
            string path = "C:/Test/";
            MonitorDirectory(path);
            Console.ReadKey();
        }

        private static void MonitorDirectory(string path)
        {
            FileSystemWatcher fileSystemWatcher = new FileSystemWatcher();
            fileSystemWatcher.Path = path;
            fileSystemWatcher.Created += FileSystemWatcher_Created;
            fileSystemWatcher.EnableRaisingEvents = true;
        }

        private static void FileSystemWatcher_Created(object sender, FileSystemEventArgs e)
        {
            string txtContents;
            string dir = "C:/Test/";
            string textFile = dir + e.Name;
            //string text = File.ReadAllText(textFile);

            FileStream fs = new FileStream(textFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
            StreamReader sr = new StreamReader(fs);
            txtContents = sr.ReadToEnd();
            sr.Close();

            string[] splitstring = txtContents.Split(new char[0], StringSplitOptions.RemoveEmptyEntries);
            DateTime now = DateTime.Now;
                 
            SqlConnection connection = new SqlConnection();
            connection.ConnectionString =
                        "Data Source=computername;" +
                        "Initial Catalog=contents;" +
                        "User id=userid;" + 
                        "Password=password;";
                    
            string query = "INSERT INTO dbo.MB1B (Field1, Field2, Field3, TStamp) VALUES (@Field1, @Field2, @Field3, @TStamp)";

            using (SqlCommand command = new SqlCommand(query, connection))
            {
                command.Parameters.AddWithValue("@Field1", splitstring[0]);
                command.Parameters.AddWithValue("@Field2", splitstring[1]);
                command.Parameters.AddWithValue("@Field3", splitstring[2]);
                command.Parameters.AddWithValue("@TStamp", now);

                connection.Open();
                int result = command.ExecuteNonQuery();

                // Check Error
                if (result < 0) 
                {
                    Console.WriteLine("Error inserting data into database!");
                }

                // connection.Close();
            }
        }
    }
}

我尝试同时使用

File.ReadAllText(textFile)
FileStream

我尝试检查这些文件是否正在使用,但我只是将 test /txt 文件从一个文件夹复制并粘贴到另一个文件夹,有时是 10 个,有时是单个。或者将 50 个测试文本文件放入一个文件夹中。

我尝试等待使用超时(因此文件未使用),并且我尝试在脚本中添加暂停。

请注意,没有任何内容被写回到文件中,我只是读取文件并将文件中的单行文本中的三个项目输入到数据库中。

c# multithreading filestream filesystemwatcher
2个回答
1
投票

引用参考文献

创建文件后就会引发 OnCreated 事件。如果将文件复制或传输到监视目录中,将立即引发 OnCreated 事件,然后引发一个或多个 OnChanged 事件。

简单来说,

OnCreated
事件并不能保证文件已完全传输,这就是为什么您会收到文件使用中异常。有API可以帮助您检测文件是否正在使用,但最方便的解决方案应该是尝试多次读取:

string txtContents;
for (int i = 0; i < 10; i++)
{
    try
    {
        txtContents = File.ReadAllText(textFile);
        break;
    }
    catch (IOException)
    {
        Thread.Sleep(10);
    }
}

-1
投票

FileStream
StreamReader
IDisposable,这意味着它们通常应与
using
关键字结合使用,以便它们消耗的资源在完成后得到正确处置。

using FileStream fs = new FileStream(textFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
using StreamReader sr = new StreamReader(fs);
txtContents = sr.ReadToEnd();

这也意味着您实际上不必显式关闭它们,因为这是在将它们放置在块末尾时完成的。就目前情况而言,您只是关闭

StreamReader
而不是
FileStream
本身,如果我没有记错的话,拥有文件句柄的是
FileStream
。所以您的文件保持打开状态。

您也可以只使用

var txtContents = File.ReadAllText(fPath);
并完全跳过对流的需要。

最后,作为参考,请参阅以下内容以了解有关 C#8 中可用的一些语法更改的详细信息:https://learn.microsoft.com/en-us/answers/questions/836600/using-block-vs-c-8 -0-using-语句

© www.soinside.com 2019 - 2024. All rights reserved.