gpt4 book ai didi

java - 读取文件时如何确定进度

转载 作者:行者123 更新时间:2023-12-02 03:04:10 25 4
gpt4 key购买 nike

我正在使用 JavaFX Task读取文本文件并将其解析为 HashMap<String, String> (使用 Mapper<String, String 对象)。我的代码功能齐全,但我希望向用户显示读取进度,因为输入文件包含超过 9000 行数据。

@Override
protected Mapper<String, String> call() throws Exception {
// Read and parse contents of source mapping file.

/* Format:
* Ignore first line of file, then:
*
* <old_name> <new_name>
* NAME_A NAME_X
* NAME_B NAME_Y
* NAME_C NAME_Z
*
* Where <old_name> = K, <new_name> = V in Mapper object.
*/

int i=beginReadingFileFromLine; // Ignore first line of file
String line;
List<String> keys = new ArrayList<>();
List<String> values = new ArrayList<>();
updateMessage("Loading data...");
while ( (line=FileUtils.readLine(sourceMappingFilePath, i)) != null ) {
// Parse line into String[] split by delim char.
String[] parsedLine = line.split(fileDelimChar);
keys.add(parsedLine[0]);
values.add(parsedLine[1]);
i++;
}
updateProgress(i, i);
updateMessage("Data loaded!");
return new Mapper<String, String>(keys, values);
}

在此代码的现有状态下,我想不出一种方法来确定我已读取了多少输入文件。方法FileUtils.readLine(sourceMappingFilePath, i)上面是一个自定义实现:

 /**
* Reads a single line, according to supplied line number from specified file.
* @param filepath
* @param lineNumber zero based index.
* @return Line from file without linefeed character. NULL if at EoF.
* @throws IOException
*/
public static String readLine(String filepath, int lineNumber) throws IOException {
FileReader fReader = new FileReader(filepath);
LineNumberReader lineNumberReader = new LineNumberReader(fReader);

String desiredLine = null;

int i=0;
String line;
while( (line=lineNumberReader.readLine()) != null) {

if(lineNumber==i) {
desiredLine=line;
}
i++;
}
lineNumberReader.close();
return desiredLine;
}

有什么建议吗?实现越简单越好 - 感谢您的宝贵时间。

最佳答案

一种简单的方法是使用底层输入流来跟踪您已读取的字节数。 Files.size() 方法将为您提供文件中的总字节数,因此这为您提供了足够的信息来计算总体进度。你可以做类似的事情

public class CountingInputStream extends InputStream implements AutoCloseable {

private long bytesRead = 0 ;

private final InputStream stream ;

public CountingInputStream(InputStream stream) {
this.stream = stream ;
}

@Override
public int read() throws IOException {
int result = stream.read() ;
if (result != -1) {
bytesRead++;
}
return result ;
}

@Override
public void close() throws IOException {
super.close();
stream.close();
}

public long getBytesRead() {
return bytesRead ;
}
}

请注意,如果将其包装在 BufferedReader 中,getBytesRead() 将返回从基础流读取的字节数,包括仍存储在缓冲区中的字节数。这对于显示进度条来说可能已经足够了(因为从缓冲区读取数据的速度非常快),但从技术上讲并不会 100% 准确。

这是 SSCCE。在我的系统上,您需要加载大约 100,000 行的文件才能看到进度条。如果您没有可用的文件,您可以创建一个(SSCCE 允许您先创建一个文件)。

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Map;
import java.util.stream.Collectors;

import javafx.application.Application;
import javafx.concurrent.Task;
import javafx.geometry.HPos;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.control.Button;
import javafx.scene.control.ButtonType;
import javafx.scene.control.Label;
import javafx.scene.control.ProgressBar;
import javafx.scene.control.TextField;
import javafx.scene.layout.GridPane;
import javafx.stage.FileChooser;
import javafx.stage.Stage;

public class ReadFileWithProgress extends Application {


public static class CountingInputStream extends InputStream implements AutoCloseable {

private long bytesRead = 0 ;

private final InputStream stream ;

public CountingInputStream(InputStream stream) {
this.stream = stream ;
}

@Override
public int read() throws IOException {
int result = stream.read() ;
if (result != -1) {
bytesRead++;
}
return result ;
}

@Override
public void close() throws IOException {
stream.close();
}

public long getBytesRead() {
return bytesRead ;
}
}

@Override
public void start(Stage primaryStage) {
GridPane root = new GridPane();
TextField numLinesField = new TextField();

FileChooser chooser = new FileChooser();

Button create = new Button("Create File...");
create.setOnAction(e -> {
int numLines = Integer.parseInt(numLinesField.getText());
File file = chooser.showSaveDialog(primaryStage);
if (file != null) {
try {
createFile(file.toPath(), numLines);
} catch (Exception exc) {
exc.printStackTrace();
}
}
});

Button loadFile = new Button("Load file");
ProgressBar progress = new ProgressBar(0);
loadFile.setOnAction(e -> {
File file = chooser.showOpenDialog(primaryStage);
if (file != null) {
Task<Map<String, String>> task = readFileTask(file.toPath());
progress.progressProperty().bind(task.progressProperty());
task.setOnSucceeded(evt -> new Alert(AlertType.INFORMATION, "File loaded", ButtonType.OK).showAndWait());
task.setOnFailed(evt -> new Alert(AlertType.ERROR, "File could not be loaded", ButtonType.OK).showAndWait());
new Thread(task).start();
}
});

root.addRow(0, new Label("Number of lines:"), numLinesField, create);
root.add(loadFile, 0, 1, 3, 1);
root.add(progress, 0, 2, 3, 1);

GridPane.setFillWidth(progress, true);
GridPane.setHalignment(progress, HPos.CENTER);
GridPane.setFillWidth(loadFile, true);
GridPane.setHalignment(loadFile, HPos.CENTER);

root.setPadding(new Insets(20));
root.setHgap(5);
root.setVgap(10);
primaryStage.setScene(new Scene(root));
primaryStage.show();
}

private Task<Map<String, String>> readFileTask(Path path) {

return new Task<Map<String, String>>() {

@Override
protected Map<String, String> call() throws IOException {
try (
CountingInputStream input = new CountingInputStream(Files.newInputStream(path));
BufferedReader in = new BufferedReader(new InputStreamReader(input));
) {

long totalBytes = Files.size(path);

return in.lines()
.peek(line -> updateProgress(input.getBytesRead(), totalBytes))
.map(line -> line.split("\t"))
.collect(Collectors.toMap(tokens -> tokens[0], tokens -> tokens[1]));
}

}

};

}

private void createFile(Path path, int numEntries) throws IOException {
try (BufferedWriter out = Files.newBufferedWriter(path)) {
for (int i = 1; i <= numEntries ; i++) {
out.write(String.format("key %d\tvalue %d%n", i, i));
}
}
}

public static void main(String[] args) {
launch(args);
}
}

关于java - 读取文件时如何确定进度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41980738/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com