如何使Java从端口读取并快速地将字节存储在文件中?
我发现java有一个问题,以及如何将1024000个数字导入到文件中。 我创建了一个从端口读取数据并将每个数字存储为ascii字符的应用程序。 但这需要很长时间。java supose会更快。我应该换什么?我应该使用其他图书馆吗?不是FileOutputStream? 当我在20分钟内进行测试时,我的文件中有100.000。。。。 多谢各位如何使Java从端口读取并快速地将字节存储在文件中?,java,performance,port,Java,Performance,Port,我发现java有一个问题,以及如何将1024000个数字导入到文件中。 我创建了一个从端口读取数据并将每个数字存储为ascii字符的应用程序。 但这需要很长时间。java supose会更快。我应该换什么?我应该使用其他图书馆吗?不是FileOutputStream? 当我在20分钟内进行测试时,我的文件中有100.000。。。。 多谢各位 public void serialEvent(SerialPortEvent evt) { if (evt.getEventType() ==
public void serialEvent(SerialPortEvent evt) {
if (evt.getEventType() == SerialPortEvent.DATA_AVAILABLE)
{
try
{
int singleData = input.read();
if(index<=1024000)
{
if(index==1024000 && singleData==42)
{
logText = "End of data. "+index+" data received ";
}
else
{
if (singleData != NEW_LINE_ASCII)
{
// logText = Integer.valueOf(singleData).toString()+"\n";
index++;
}
writeFile(singleData, fileName, false);
}
}
}
catch (Exception e)
{
logText = "Failed to read data. (" + e.toString() + ")";
}
}
}
public void writeFile(int data, String fileName, boolean endOfFile) throws IOException {
FileOutputStream xfos = new FileOutputStream(fileName,true);
DataOutputStream xdos = new DataOutputStream(xfos);
xdos.writeBytes(Integer.toString(data)+"\n"); // writes Ascii
xdos.close();
}
public void serialEvent(SerialPortEvent evt){
if(evt.getEventType()==SerialPortEvent.DATA\u可用)
{
尝试
{
int singleData=input.read();
if(index停止打开和关闭每个条目的文件,并开始缓冲。创建一个int[]以在整数进入时保存整数,并且仅在有大量整数后写入。此外,根据环境的不同,您可以保持流打开,并且仅在退出时关闭它们(或读取1024000个条目)
现在,每次你得到一个整数,你就打开文件,一直运行到最后,写一行,然后关闭它。打开和关闭都很昂贵,你当然可以这样写,这样就不必每次都这样做了。停止为每个条目打开和关闭文件,并开始缓冲。创建一个int[]在整数进入时保存它们,并且只有在具有一定数量的整数后才进行写入。此外,根据环境的不同,您可以保持流处于打开状态,并且只能在退出时关闭它们(或读取1024000个条目)
现在,每次你得到一个整数,你就打开文件,一直运行到最后,写一行,然后关闭它。打开和关闭都很昂贵,你当然可以这样写,这样就不必每次都这样做了。将输出文件保持打开状态,直到你完成写入。每次写入后关闭文件,操作系统就会写入您刚刚写入磁盘的单个字节。无论使用哪种语言,这都很慢,这只是文件关闭操作带来的保证的结果。此外,每次打开文件时查找文件结尾也可能需要相当长的时间
利用流的大容量读写方法。不要读写单个字符,而是使用大小合理的字节[](8K=8192通常足够)。或者,通过将流包装到BufferedInputStream/BufferedOutputStream(开销稍高,但代码更简单)来缓冲流
本质上,您应该做的是在开始时打开输入和输出流一次,并保持它们都打开,直到所有数据都通过。使用块传输或缓冲流,主要限制因素将是硬件(在您的情况下是串行端口).将输出文件保持打开状态,直到您完成写入。每次写入后关闭该文件会导致操作系统将您刚写入磁盘的单个字节写入磁盘。无论使用何种语言,这都很慢,这只是文件关闭操作带来的保证的结果。此外,每次打开文件时都要找到文件的结尾也可能需要退出e一段时间后,文件变长
利用流的大容量读写方法。不要读写单个字符,而是使用大小合理的字节[](8K=8192通常足够)。或者,通过将流包装到BufferedInputStream/BufferedOutputStream(开销稍高,但代码更简单)来缓冲流
本质上,您应该做的是在开始时打开输入和输出流一次,并保持它们都打开,直到所有数据都通过。使用块传输或缓冲流,主要限制因素将是硬件(在您的情况下是串行端口).谢谢大家,但我相信我在开始时只打开了一个输入输出流。我在GUI Connect中有一个按钮,用于执行此操作:连接到端口初始化流
private void btnConnectActionPerformed(java.awt.event.ActionEvent evt) {
communicator.connect();
if (communicator.getConnected() == true)
{
if (communicator.initIOStream() == true)
{
communicator.initListener();
}
}
}
//connect to the selected port in the combo box
public void connect()
{
fileName="xxxx"+"_"+new SimpleDateFormat("yyyy-MM-dd hh-mm-ss").format(new Date())+".txt";
String selectedPort = (String)window.cboxPorts.getSelectedItem();
selectedPortIdentifier = (CommPortIdentifier)portMap.get(selectedPort);
index=0;
vec.clear();
CommPort commPort = null;
try
{
//the method below returns an object of type CommPort
commPort = selectedPortIdentifier.open("TigerControlPanel", TIMEOUT);
//the CommPort object can be casted to a SerialPort object
serialPort = (SerialPort)commPort;
output = serialPort.getOutputStream();
//for controlling GUI elements
setConnected(true);
window.txtLog.setText(null);
//logging
logText = selectedPort + " opened successfully.";
window.txtLog.setForeground(Color.black);
window.txtLog.append(logText + "\n");
}
catch (PortInUseException e)
{
logText = selectedPort + " is in use. (" + e.toString() + ")";
window.txtLog.setForeground(Color.RED);
window.txtLog.append(logText + "\n");
}
catch (Exception e)
{
if(selectedPort==null)
{
logText = " No port selected";
}else
logText = "Failed to open " + selectedPort + "(" + e.toString() + ")";
window.txtLog.append(logText + "\n");
window.txtLog.setForeground(Color.RED);
}
}
//open the input and output streams
public boolean initIOStream()
{
//return value for whather opening the streams is successful or not
boolean successful = false;
try {
//
input = serialPort.getInputStream();
output = serialPort.getOutputStream();
successful = true;
return successful;
}
catch (IOException e) {
logText = "I/O Streams failed to open. (" + e.toString() + ")";
window.txtLog.setForeground(Color.red);
window.txtLog.append(logText + "\n");
return successful;
}
}
//starts the event listener that knows whenever data is available to be read
public void initListener()
{
try
{
serialPort.addEventListener(this);
serialPort.notifyOnDataAvailable(true);
}
catch (TooManyListenersException e)
{
logText = "Too many listeners. (" + e.toString() + ")";
window.txtLog.setForeground(Color.red);
window.txtLog.append(logText + "\n");
}
try {
output.write(messageString.getBytes());
// output.write(System.getProperty("java.library.path").getBytes()) ;
} catch (IOException e) { }
}
谢谢大家,但我相信我在开始时只打开了一个输入输出流。我在GUI Connect中有一个按钮,用于执行此操作:连接到端口初始化流
private void btnConnectActionPerformed(java.awt.event.ActionEvent evt) {
communicator.connect();
if (communicator.getConnected() == true)
{
if (communicator.initIOStream() == true)
{
communicator.initListener();
}
}
}
//connect to the selected port in the combo box
public void connect()
{
fileName="xxxx"+"_"+new SimpleDateFormat("yyyy-MM-dd hh-mm-ss").format(new Date())+".txt";
String selectedPort = (String)window.cboxPorts.getSelectedItem();
selectedPortIdentifier = (CommPortIdentifier)portMap.get(selectedPort);
index=0;
vec.clear();
CommPort commPort = null;
try
{
//the method below returns an object of type CommPort
commPort = selectedPortIdentifier.open("TigerControlPanel", TIMEOUT);
//the CommPort object can be casted to a SerialPort object
serialPort = (SerialPort)commPort;
output = serialPort.getOutputStream();
//for controlling GUI elements
setConnected(true);
window.txtLog.setText(null);
//logging
logText = selectedPort + " opened successfully.";
window.txtLog.setForeground(Color.black);
window.txtLog.append(logText + "\n");
}
catch (PortInUseException e)
{
logText = selectedPort + " is in use. (" + e.toString() + ")";
window.txtLog.setForeground(Color.RED);
window.txtLog.append(logText + "\n");
}
catch (Exception e)
{
if(selectedPort==null)
{
logText = " No port selected";
}else
logText = "Failed to open " + selectedPort + "(" + e.toString() + ")";
window.txtLog.append(logText + "\n");
window.txtLog.setForeground(Color.RED);
}
}
//open the input and output streams
public boolean initIOStream()
{
//return value for whather opening the streams is successful or not
boolean successful = false;
try {
//
input = serialPort.getInputStream();
output = serialPort.getOutputStream();
successful = true;
return successful;
}
catch (IOException e) {
logText = "I/O Streams failed to open. (" + e.toString() + ")";
window.txtLog.setForeground(Color.red);
window.txtLog.append(logText + "\n");
return successful;
}
}
//starts the event listener that knows whenever data is available to be read
public void initListener()
{
try
{
serialPort.addEventListener(this);
serialPort.notifyOnDataAvailable(true);
}
catch (TooManyListenersException e)
{
logText = "Too many listeners. (" + e.toString() + ")";
window.txtLog.setForeground(Color.red);
window.txtLog.append(logText + "\n");
}
try {
output.write(messageString.getBytes());
// output.write(System.getProperty("java.library.path").getBytes()) ;
} catch (IOException e) { }
}
谢谢大家的建议。我更改了代码,使用了一个缓冲字节[]来获取数据,然后将它们存储在一个文件中。时间缩短得难以置信。它能在1.31秒内读取1024001个数据。问题是我能让它变快吗?这只是数字,只需要几秒钟。这是代码
if (evt.getEventType() == SerialPortEvent.DATA_AVAILABLE)
{
int available =0;
int bytesRead;
try {
available = input.available();
} catch (IOException e) {
e.printStackTrace();
}
byte[] buffer = new byte[1024001];
try {
while ( (bytesRead = input.read(buffer)) > 0 ) {
byte[] newData = new byte[data.length + bytesRead];
// copy data previously read
System.arraycopy(data, 0, newData, 0, data.length);
// append data newly read
System.arraycopy(buffer, 0, newData, data.length, bytesRead);
// discard the old array in favour of the new one
data = newData;
if(data.length==1024001)
{
logText = "End of data. "+data.length+" data received "+fileName;
window.txtLog.setForeground(Color.BLUE);
window.txtLog.append(logText + "\n");
writeFile(data, fileName, false);
}
bytesRead++;
我还为端口设置了这些参数
serialPort.setSerialPortParams(115600,
SerialPort.DATABITS_8,
SerialPort.STOPBITS_1,
SerialPort.PARITY_NONE);
有没有办法将串行端口速度设置为满?谢谢大家的建议。我更改了代码并使用了缓冲字节[]获取数据,然后将它们全部存储在一个文件中。时间缩短得令人难以置信。它在1.31秒内读取1024001个数据。问题是我能让它更精确吗?这只是数字,只需要几秒钟。下面是代码
if (evt.getEventType() == SerialPortEvent.DATA_AVAILABLE)
{
int available =0;
int bytesRead;
try {
available = input.available();
} catch (IOException e) {
e.printStackTrace();
}
byte[] buffer = new byte[1024001];
try {
while ( (bytesRead = input.read(buffer)) > 0 ) {
byte[] newData = new byte[data.length + bytesRead];
// copy data previously read
System.arraycopy(data, 0, newData, 0, data.length);
// append data newly read
System.arraycopy(buffer, 0, newData, data.length, bytesRead);
// discard the old array in favour of the new one
data = newData;
if(data.length==1024001)
{
logText = "End of data. "+data.length+" data received "+fileName;
window.txtLog.setForeground(Color.BLUE);
window.txtLog.append(logText + "\n");
writeFile(data, fileName, false);
}
bytesRead++;
我还为端口设置了这些参数
serialPort.setSerialPortParams(115600,
SerialPort.DATABITS_8,
SerialPort.STOPBITS_1,
SerialPort.PARITY_NONE);
有没有办法将串行端口速度设置为完全速度?您确定瓶颈是java写入文件和网络,即从端口读取?为什么要打开文件并在每次读取时追加?为什么不在未完成时保持文件打开?打开文件一次,您应该能够在不到40 MB的时间内写入40 MB一秒钟。你确定瓶颈是java写入文件和网络,即从端口读取吗?为什么要打开文件并在每次读取时追加?为什么不在未完成时保持文件打开?打开文件一次,你应该能够在不到一秒钟内写入40 MB。谢谢大家,但我相信我只打开了一个是开始的输入输出流。我在GUI Connect中有一个按钮,它可以执行以下操作:连接到端口初始化流您还没有显示writeFile的代码(singleData、fileName、false);我们怀疑您需要打开/关闭每个字节。谢谢大家的建议。我更改了代码,并使用了缓冲字节[]获取数据和t