在 Node.js 中使用 WriteStream 和替换文件写入时出现问题
Issue when writing with WriteStream and replace-in-file in Node.js
我希望能够在运行时写入文件,同时还能够 replace/delete 文件中的某些行。
对于写作,我使用的是 fs.WriteStream 而对于替换,我使用的是 replace-in-file 库。
我写了很多次所以我不能使用fs.writeFile
我尝试在文件中写入几行,替换一些文本,然后添加新行。替换后,流的指针似乎不再指向文件末尾。
import * as fs from "fs";
const stream = fs.createWriteStream("./file.txt");
const replace = require("replace-in-file");
const option = {
files: "./file.txt",
from: /Second/,
to: "After the first"
};
stream.write("First line \n");
stream.write("Second line \n");
stream.write("Third line \n");
replace(option)
.then(results => {
console.log("Replacement results:", results);
stream.write("X");
})
.catch(error => {
console.error("Error occurred:", error);
});
我希望文件包含以下文本:
First line
After the first line
Third line
X
不幸的是它包含:
First line
The after the first line XThird line
我无法解决我遇到的问题,但我能够在运行时相对更新文件。我创建了一个 File
class ,它将文件的数据存储在一个字符串中。然后,我只在对文件进行重要更改时才写入文件。
有一些未包含但使用 fs
创建起来相当简单的 Util 函数。
class
export {};
import * as Util from "../Utility/Util";
export class File {
/** A class to represent a file. Data isn't saved until you close/flush the file */
private text: string; // Represents the text the file contains
private path: string; // The path of the file
private isOpen: boolean; // True when the file is open; False otherwise
constructor(path: string) {
this.path = path;
this.text = "";
this.isOpen = false;
}
open(): void {
/**Must run before writing to file */
if (this.isOpen) return; // Make sure file isn't opened twice
Util.Log(`Opening file: ${this.path}`, 4);
// Create the file if it doesn't already exist
if (!Util.PathExists(this.path)) {
Util.CreateFile(this.path);
}
this.isOpen = true;
this.text = Util.ReadFile(this.path);
}
append(data: string): void {
/** Adds data to the file */
try {
this.text += data;
} catch (err) {
const e: Error = err;
if (e.name === "RangeError") {
const errArr: string[] = [
"Error: RangeError",
"While writing data to files, the File class uses a string to save the data. That data is too big.",
"This happens every time you will try to write to much data to a file.",
"You must make the csv log files smaller."
];
Util.SHUT_DOWN(errArr.join("\n"), e);
}
}
}
replace(oldData: string, newData: string): void {
/** Replace the first occurrence oldData with newData */
this.text = this.text.replace(new RegExp(oldData, ""), newData);
}
isEmpty(): boolean {
/** Returns true if the file is completely empty */
return this.text == "";
}
getLineWith(text: string): string {
/** Returns the first line with the text in it */
let lines = this.getLines();
for (let i = 0; i < lines.length; i++) {
if (lines[i].includes(text)) {
return lines[i];
}
}
return "";
}
deleteLineWith(data: string[]): void {
/** Deletes the first line in the file that contains all of the strings in the array */
let lines = this.getLines(); // Get all lines in the
for (let i = 0; i < lines.length; i++) {
let allDataFound = true;
for (let g = 0; g < data.length; g++) {
allDataFound = allDataFound && lines[i].includes(data[g]);
}
if (allDataFound) {
const newLines = lines
.slice(0, i)
.concat(lines.slice(i + 1, lines.length));
this.setTextByLines(newLines);
// this.text = newLines.join("\n");
}
}
}
getLines(): string[] {
/** Returns an array of the lines in the file */
return this.text.split("\n");
}
setTextByLines(lines: string[]) {
/** Sets the file's text given an array of lines */
this.text = lines.join("\n");
}
close() {
/** Close the file. Must run this to save changes */
if (!this.isOpen) return; // Prevent multiple closings
Util.Log(`Closing file: ${this.path}`, 3);
this.flush();
this.isOpen = false;
}
flush() {
/** Writes to the file the text it supposed to have at the moment*/
if (!this.isOpen) {
return;
}
Util.WriteToFile(this.path, this.text);
}
getPath(): string {
/** Get the path of the file */
return this.path;
}
}
用法:
import {File} from './FileHandler'
let f = new File('./newFile.txt')
f.open() // File contains 0 lines
f.append('First line\n') // File contains 0 lines
f.append('Second line\n') // File contains 0 lines
f.flush() // File contains 2 lines
f.append('Third line\n') // File contains 2 lines
f.append('Fourth line\n') // File contains 2 lines
f.close() // File contains 4 lines
// Note: If the file had already X lines they would not be deleted.
我希望能够在运行时写入文件,同时还能够 replace/delete 文件中的某些行。
对于写作,我使用的是 fs.WriteStream 而对于替换,我使用的是 replace-in-file 库。
我写了很多次所以我不能使用fs.writeFile
我尝试在文件中写入几行,替换一些文本,然后添加新行。替换后,流的指针似乎不再指向文件末尾。
import * as fs from "fs";
const stream = fs.createWriteStream("./file.txt");
const replace = require("replace-in-file");
const option = {
files: "./file.txt",
from: /Second/,
to: "After the first"
};
stream.write("First line \n");
stream.write("Second line \n");
stream.write("Third line \n");
replace(option)
.then(results => {
console.log("Replacement results:", results);
stream.write("X");
})
.catch(error => {
console.error("Error occurred:", error);
});
我希望文件包含以下文本:
First line
After the first line
Third line
X
不幸的是它包含:
First line
The after the first line XThird line
我无法解决我遇到的问题,但我能够在运行时相对更新文件。我创建了一个 File
class ,它将文件的数据存储在一个字符串中。然后,我只在对文件进行重要更改时才写入文件。
有一些未包含但使用 fs
创建起来相当简单的 Util 函数。
class
export {};
import * as Util from "../Utility/Util";
export class File {
/** A class to represent a file. Data isn't saved until you close/flush the file */
private text: string; // Represents the text the file contains
private path: string; // The path of the file
private isOpen: boolean; // True when the file is open; False otherwise
constructor(path: string) {
this.path = path;
this.text = "";
this.isOpen = false;
}
open(): void {
/**Must run before writing to file */
if (this.isOpen) return; // Make sure file isn't opened twice
Util.Log(`Opening file: ${this.path}`, 4);
// Create the file if it doesn't already exist
if (!Util.PathExists(this.path)) {
Util.CreateFile(this.path);
}
this.isOpen = true;
this.text = Util.ReadFile(this.path);
}
append(data: string): void {
/** Adds data to the file */
try {
this.text += data;
} catch (err) {
const e: Error = err;
if (e.name === "RangeError") {
const errArr: string[] = [
"Error: RangeError",
"While writing data to files, the File class uses a string to save the data. That data is too big.",
"This happens every time you will try to write to much data to a file.",
"You must make the csv log files smaller."
];
Util.SHUT_DOWN(errArr.join("\n"), e);
}
}
}
replace(oldData: string, newData: string): void {
/** Replace the first occurrence oldData with newData */
this.text = this.text.replace(new RegExp(oldData, ""), newData);
}
isEmpty(): boolean {
/** Returns true if the file is completely empty */
return this.text == "";
}
getLineWith(text: string): string {
/** Returns the first line with the text in it */
let lines = this.getLines();
for (let i = 0; i < lines.length; i++) {
if (lines[i].includes(text)) {
return lines[i];
}
}
return "";
}
deleteLineWith(data: string[]): void {
/** Deletes the first line in the file that contains all of the strings in the array */
let lines = this.getLines(); // Get all lines in the
for (let i = 0; i < lines.length; i++) {
let allDataFound = true;
for (let g = 0; g < data.length; g++) {
allDataFound = allDataFound && lines[i].includes(data[g]);
}
if (allDataFound) {
const newLines = lines
.slice(0, i)
.concat(lines.slice(i + 1, lines.length));
this.setTextByLines(newLines);
// this.text = newLines.join("\n");
}
}
}
getLines(): string[] {
/** Returns an array of the lines in the file */
return this.text.split("\n");
}
setTextByLines(lines: string[]) {
/** Sets the file's text given an array of lines */
this.text = lines.join("\n");
}
close() {
/** Close the file. Must run this to save changes */
if (!this.isOpen) return; // Prevent multiple closings
Util.Log(`Closing file: ${this.path}`, 3);
this.flush();
this.isOpen = false;
}
flush() {
/** Writes to the file the text it supposed to have at the moment*/
if (!this.isOpen) {
return;
}
Util.WriteToFile(this.path, this.text);
}
getPath(): string {
/** Get the path of the file */
return this.path;
}
}
用法:
import {File} from './FileHandler'
let f = new File('./newFile.txt')
f.open() // File contains 0 lines
f.append('First line\n') // File contains 0 lines
f.append('Second line\n') // File contains 0 lines
f.flush() // File contains 2 lines
f.append('Third line\n') // File contains 2 lines
f.append('Fourth line\n') // File contains 2 lines
f.close() // File contains 4 lines
// Note: If the file had already X lines they would not be deleted.