在java中通过asynchronousFileChannel写入时丢失数据
Posted
技术标签:
【中文标题】在java中通过asynchronousFileChannel写入时丢失数据【英文标题】:losing data while writing through asynchronousFileChannel in java 【发布时间】:2013-09-20 04:59:36 【问题描述】:我正在尝试使用 asynchronousFileChannel 将日期写入文本文件。我使用 AsynchronousFileChannel 制作了程序的 3 个 jar 文件,并通过命令提示符同时编译了所有 3 个 jar,以读取 3 个不同的文本文件并输出到一个公共临时文件
我的测试文件中有 2000 条记录(3) 需要读取,但是普通临时文件中的输出缺少一些记录,输出应该有 6000 条记录但它只显示 5366 或 5666 或有时少于那个。
我无法弄清楚为什么某些数据会丢失,因为它是 asynchronousFileChannel 的功能。 这是使用异步文件通道的java程序的代码。
class Writer()
public void writeOut(ReadableData fileData)
throws InterruptedException
Path file = null;
AsynchronousFileChannel asynchFileChannel = null;
String filePath = tempFileName;
try
file = Paths.get(filePath);
asynchFileChannel = AsynchronousFileChannel.open(file,
StandardOpenOption.WRITE, StandardOpenOption.CREATE);
CompletionHandler<Integer, Object> handler = new CompletionHandler<Integer, Object>()
@Override
public void completed(Integer result, Object attachment)
if (result == Integer.MAX_VALUE)
log.debug("Attachment: " + attachment + " " + result
+ " bytes written");
log.debug("CompletionHandler Thread ID: "
+ Thread.currentThread().getId());
result++;
@Override
public void failed(Throwable e, Object attachment)
try
throw e;
catch (Throwable e1)
e1.printStackTrace();
log.debug("File Write Failed Exception:");
e.printStackTrace();
;
String printData = fileData.getId() + "|"
+ fileData.getName() + "|" + fileData.getEmpId()
+ "|" + fileData.getServieId() + "|" + "\n";
asynchFileChannel.write(ByteBuffer.wrap(printData.getBytes()),
asynchFileChannel.size(), "file write", handler);
log.debug(printData);
catch (IOException e)
e.printStackTrace();
log.error(e.getMessage());
finally
这是我从 3 个文件中读取数据的课程:
public class FileReader1
static Logger log = Logger.getLogger(FileHandlerNorthBoundMain.class
.getName());
Writer wrO=new Writer();
public static void main(String[] args) throws IOException,
IllegalFileFormatException, InterruptedException
String filePath = "C:\\Users\\Public\\testdata1.csv"; //"C:\\Users\\Public\\testdata2.csv"; "C:\\Users\\Public\\testdata3.csv";
File file = new File(filePath);
log.info("Fetching data.... from: " + filePath);
ArrayList<ReadableData> list = new ArrayList<ReadableData>();
FileInputStream fs = null;
BufferedReader reader = null;
String Name;
int Id, EmpId, ServiceId;
ReadableData readableData = null;
int count = 0;
fs = new FileInputStream(file);
reader = new BufferedReader(new InputStreamReader(fs));
String line = reader.readLine();
while (line != null)
StringTokenizer st = new StringTokenizer(line, "\\|");
while (st.hasMoreTokens())
try
Id = Integer.parseInt(st.nextToken());
Name = st.nextToken();
EmpId = Integer.parseInt(st.nextToken());
ServiceId = Integer.parseInt(st.nextToken());
readableData = new ReadableData(Id,
, Name, EmpId,ServiceId);
wrO.writeOut(readableData);
list.add(count, readableData);
count = count++;
catch (Exception ex)
log.error("Illegal File Format");
throw new IllegalFileFormatException("Illegal File Format");
line = reader.readLine();
reader.close();
【问题讨论】:
【参考方案1】:使用 asynchronousFileChannel lock() 使用以下代码部分修改您的 Writer 类
byte[] test = printData.getBytes();
Future<FileLock> featureLock = asynchFileChannel.lock();
log.info("Waiting for the file to be locked ...");
FileLock lock = featureLock.get();
if (lock.isValid())
log.debug(printData);
Future<Integer> featureWrite = asynchFileChannel.write(
ByteBuffer.wrap(test), asynchFileChannel.size());
log.info("Waiting for the bytes to be written ...");
int written = featureWrite.get();
log.info("I’ve written " + written + " bytes into "
+ file.getFileName() + " locked file!");
lock.release();
【讨论】:
【参考方案2】:这可能是因为 asynchronousFileChannel 是线程安全的,但 Bytebuffer 不是,应注意确保在操作完成之前不会访问缓冲区。
查看文档http://openjdk.java.net/projects/nio/javadoc/java/nio/channels/AsynchronousFileChannel.html
【讨论】:
尝试这样做,但输出文件中仍然缺少数据。以上是关于在java中通过asynchronousFileChannel写入时丢失数据的主要内容,如果未能解决你的问题,请参考以下文章