java中如何读取文件_如何使用Java从正在写入的文件中读取?

如何使用Java从正在写入的文件中读取?

我有一个将信息写入文件的应用程序。 在执行后使用此信息来确定应用程序的通过/失败/正确性。 我希望能够在写入文件时读取文件,以便我可以实时进行这些通过/失败/正确性检查。

我认为可以这样做,但使用Java时涉及到的问题是什么? 如果读取符合写入,它是否只是等待更多写入,直到文件关闭,或者读取是否会抛出异常? 如果是后者,我该怎么办?

我的直觉目前正在推动我走向BufferedStreams。 这是要走的路吗?

9个解决方案

35 votes

无法使用FileChannel.read(ByteBuffer)使示例正常工作,因为它不是阻塞读取。 但是,让下面的代码工作:

boolean running = true;

BufferedInputStream reader = new BufferedInputStream(new FileInputStream( "out.txt" ) );

public void run() {

while( running ) {

if( reader.available() > 0 ) {

System.out.print( (char)reader.read() );

}

else {

try {

sleep( 500 );

}

catch( InterruptedException ex ) {

running = false;

}

}

}

}

当然同样的事情可以作为计时器而不是线程,但我把它留给程序员。 我还在寻找更好的方法,但现在这对我有用。

哦,我会告诉他们:我使用的是1.4.2。 是的我知道我还在石器时代。

Joseph Gordon answered 2019-08-12T12:39:36Z

8 votes

如果您想在写入文件时读取文件并且只读取新内容,则以下内容将帮助您实现相同的目标。

要运行此程序,您将从命令提示符/终端窗口启动它并传递文件名以进行读取。 除非你杀了程序,否则它会读取文件。

java FileReader c:\ myfile.txt

当您键入一行文本时,将其从记事本中保存,您将看到控制台中打印的文本。

public class FileReader {

public static void main(String args[]) throws Exception {

if(args.length>0){

File file = new File(args[0]);

System.out.println(file.getAbsolutePath());

if(file.exists() && file.canRead()){

long fileLength = file.length();

readFile(file,0L);

while(true){

if(fileLength

readFile(file,fileLength);

fileLength=file.length();

}

}

}

}else{

System.out.println("no file to read");

}

}

public static void readFile(File file,Long fileLength) throws IOException {

String line = null;

BufferedReader in = new BufferedReader(new java.io.FileReader(file));

in.skip(fileLength);

while((line = in.readLine()) != null)

{

System.out.println(line);

}

in.close();

}

}

tiger.spring answered 2019-08-12T12:40:22Z

5 votes

您还可以查看java通道来锁定文件的一部分。

[http://java.sun.com/javase/6/docs/api/java/nio/channels/FileChannel.html]

FileChannel的此功能可能是一个开始

lock(long position, long size, boolean shared)

调用此方法将阻塞,直到可以锁定该区域

Frederic Morin answered 2019-08-12T12:41:08Z

5 votes

我完全同意约书亚的回应,Tailer在这种情况下适合这份工作。 这是一个例子:

它在文件中每150毫秒写一行,同时每2500毫秒读取一个相同的文件

public class TailerTest

{

public static void main(String[] args)

{

File f = new File("/tmp/test.txt");

MyListener listener = new MyListener();

Tailer.create(f, listener, 2500);

try

{

FileOutputStream fos = new FileOutputStream(f);

int i = 0;

while (i < 200)

{

fos.write(("test" + ++i + "\n").getBytes());

Thread.sleep(150);

}

fos.close();

}

catch (Exception e)

{

e.printStackTrace();

}

}

private static class MyListener extends TailerListenerAdapter

{

@Override

public void handle(String line)

{

System.out.println(line);

}

}

}

ToYonos answered 2019-08-12T12:41:42Z

3 votes

答案似乎是&#34;没有&#34; ......和&#34;是&#34;。 似乎没有真正的方法可以知道文件是否可以被另一个应用程序写入。 因此,从这样的文件中读取只会继续进行,直到内容耗尽为止。 我接受了Mike的建议并编写了一些测试代码:

Writer.java将一个字符串写入文件,然后在将另一行写入文件之前等待用户按Enter键。 这个想法是它可以启动,然后读者可以开始看看它如何应对&#34; partial&#34; 文件。 我写的读者是在Reader.java中。

Writer.java

public class Writer extends Object

{

Writer () {

}

public static String[] strings =

{

"Hello World",

"Goodbye World"

};

public static void main(String[] args)

throws java.io.IOException {

java.io.PrintWriter pw =

new java.io.PrintWriter(new java.io.FileOutputStream("out.txt"), true);

for(String s : strings) {

pw.println(s);

System.in.read();

}

pw.close();

}

}

Reader.java

public class Reader extends Object

{

Reader () {

}

public static void main(String[] args)

throws Exception {

java.io.FileInputStream in = new java.io.FileInputStream("out.txt");

java.nio.channels.FileChannel fc = in.getChannel();

java.nio.ByteBuffer bb = java.nio.ByteBuffer.allocate(10);

while(fc.read(bb) >= 0) {

bb.flip();

while(bb.hasRemaining()) {

System.out.println((char)bb.get());

}

bb.clear();

}

System.exit(0);

}

}

不保证此代码是最佳实践。

这留下了Mike建议的选项,定期检查是否有新数据要从文件中读取。 然后,当确定读取完成时,这需要用户干预以关闭文件读取器。 或者,需要使读者了解文件的内容并能够确定和结束写入条件。 如果内容是XML,则可以使用文档结尾来表示这一点。

Anthony Cramp answered 2019-08-12T12:42:48Z

1 votes

不是Java本身,但你可能会遇到一些问题,你已经写了一些文件,但它还没有实际编写 - 它可能在某个地方的缓存中,并且从同一个文件读取可能实际上不是 给你新的信息。

短版本 - 使用flush()或任何相关的系统调用来确保您的数据实际写入文件。

注意我不是在谈论操作系统级磁盘缓存 - 如果你的数据进入这里,它应该在这之后出现在read()中。 可能是语言本身缓存写入,等待缓冲区填满或文件被刷新/关闭。

Matthew Schinckel answered 2019-08-12T12:43:33Z

1 votes

有一个开源Java图形尾部可以做到这一点。

[https://stackoverflow.com/a/559146/1255493]

public void run() {

try {

while (_running) {

Thread.sleep(_updateInterval);

long len = _file.length();

if (len < _filePointer) {

// Log must have been jibbled or deleted.

this.appendMessage("Log file was reset. Restarting logging from start of file.");

_filePointer = len;

}

else if (len > _filePointer) {

// File must have had something added to it!

RandomAccessFile raf = new RandomAccessFile(_file, "r");

raf.seek(_filePointer);

String line = null;

while ((line = raf.readLine()) != null) {

this.appendLine(line);

}

_filePointer = raf.getFilePointer();

raf.close();

}

}

}

catch (Exception e) {

this.appendMessage("Fatal error reading log file, log tailing has stopped.");

}

// dispose();

}

Rodrigo Menezes answered 2019-08-12T12:44:07Z

0 votes

我从来没有尝试过,但你应该编写一个测试用例,看看在你到达终点后从流中读取是否有效,无论是否有更多的数据写入文件。

您是否有理由不能使用管道输入/输出流? 是从同一个应用程序写入和读取数据(如果是,您有数据,为什么需要从文件中读取)?

否则,可能会读到文件末尾,然后监视更改并寻找您离开的地方并继续......但要注意竞争条件。

Mike Stone answered 2019-08-12T12:44:48Z

0 votes

您无法使用FileInputStream,FileReader或RandomAccessFile读取从另一个进程打开的文件。

但直接使用FileChannel将起作用:

private static byte[] readSharedFile(File file) throws IOException {

byte buffer[] = new byte[(int) file.length()];

final FileChannel fc = FileChannel.open(file.toPath(), EnumSet.of(StandardOpenOption.READ));

final ByteBuffer dst = ByteBuffer.wrap(buffer);

fc.read(dst);

fc.close();

return buffer;

}

bebbo answered 2019-08-12T12:45:23Z

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值