我最近遇到了一个问题,我无法找到适合我需求的解决方案。所以我试图逐行读取文本文件,并检查该行是否是一个特定的字符串。如果文件不包含该字符串,则应将其写入文件。这是我目前的问题。
if ($credentials_file = checkServiceAccountCredentialsFile()) {
// set the location manually
$client->setAuthConfig($credentials_file);
} elseif (getenv('GOOGLE_APPLICATION_CREDENTIALS')) {
// use the application default credentials
$client->useApplicationDefaultCredentials();
} else {
echo missingServiceAccountDetailsWarning();
return;
}
$client->setSubject('j******@gmail.com');
$client->setScopes(['https://www.googleapis.com/auth/drive']);
$service = new Google_Service_Drive($client);
$files = $service->files->listFiles();
我已经读过有关同时读取和写入文件的问题,但我想知道是否有办法实现这一目标。任何帮助表示赞赏!
答案 0 :(得分:1)
使用FileStream并将它用于StreamReader和StreamWriter,下面是添加或更改textFile行的示例:
public static void ChangeOrAddLine(string filePath, string newLine, string oldLine = "")
{
using (FileStream fs = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.Read))
using (StreamReader sr = new StreamReader(fs))
using (StreamWriter sw = new StreamWriter(fs))
{
List<string> lines = sr.ReadToEnd().Split(new string[] { "\r\n" }, StringSplitOptions.None).ToList();
fs.Position = 0;
bool lineFound = false;
if (oldLine != "")
for (int i = 0; i < lines.Count; i++)
if (lines[i] == oldLine)
{
lines[i] = newLine;
lineFound = true;
break;
}
if (!lineFound)
lines.Add(newLine);
sw.Write(string.Join("\r\n", lines));
fs.SetLength(fs.Position);
}
}
FileAccess.ReadWrite打开文件进行读写
FileShare.Read让其他程序也可以阅读
答案 1 :(得分:1)
请注意,您当前的方法效率非常低,需要您的代码从磁盘读取文件以搜索每个字符串。
您将无法使用两个不同的流同时读取和写入同一文件,就像您尝试的那样。以下是我建议的一些策略,不知道更多:
如果文件很小,请将while文件加载到List中,然后关闭阅读器。然后,您可以在列表中搜索每个字符串:
if(!list.Any(write))
// Write the string to the file
这将非常快,因为列表在内存中并且文件只读一次(假设它相当小 - 比如说&lt; 5000行,虽然它也适用于更大的文件)。
另一种方法是将缺少的字符串添加到List中,一旦识别出所有缺少的字符串,请关闭阅读器并使用writer添加字符串。这仍然是低效的,因为您正在为每次查找读取文件(可能很大),所以
此方法的一个改进是读取文件,并针对您可能要添加的所有行检查每一行。这意味着您只需阅读一次文件并浏览每行的播放列表集合,这将更有效,因为它在内存中。假设你只有几行你正在检查 - 比如你要添加的一些新歌,这会多次提高效率。
如果文件变得非常大,您可能需要某种索引查找方法。
答案 2 :(得分:1)
未建议的另一个选项是在原始文件上打开阅读器,即临时文件上的编写者。从原始写入读取临时文件并添加缺少的行,然后用临时文件替换原始文件。