
本文介绍了如何在 Java Structs 框架中,基于 ArrayList 的值动态生成 CSV 文件,并将其上传到 FTP 服务器。核心思路是使用 ByteArrayOutputStream 和 ByteArrayInputStream 在内存中创建 CSV 数据流,避免了实际文件的创建,从而提高了效率。最后,通过 FTP 客户端将数据流上传到指定服务器。
在传统的 Java Structs 应用中,生成 CSV 文件并上传到 FTP 服务器通常涉及以下步骤:先将数据写入磁盘文件,然后读取该文件并上传。然而,这种方法效率较低,因为涉及磁盘 I/O 操作。更高效的方法是在内存中生成 CSV 数据,然后直接将其作为 InputStream 上传到 FTP 服务器,从而避免了磁盘 I/O。
以下是如何在 Java 中实现这一目标的详细步骤:
1. 准备数据
立即学习“Java免费学习笔记(深入)”;
首先,假设我们有一个包含业务数据和位置数据的 ArrayList,需要将其写入 CSV 文件。
String[] business = {"Business1", "Business2", "Business3"};
String[] position = {"Position1", "Position2", "Position3"};2. 使用 ByteArrayOutputStream 和 ByteArrayInputStream 生成 InputStream
使用 ByteArrayOutputStream 将数据写入内存,然后使用 ByteArrayInputStream 从内存中读取数据。
import java.io.*;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try (Writer writer = new OutputStreamWriter(bos)) {
// 写入 CSV 文件的头部(可选)
writer.write("Business,Position\n");
// 写入数据
for (int i = 0; i < business.length; i++) {
writer.write(business[i] + "," + position[i] + "\n");
}
writer.flush(); // 确保所有数据都写入到 ByteArrayOutputStream
} catch (IOException e) {
e.printStackTrace();
// 处理IO异常
}
InputStream inputStream = new ByteArrayInputStream(bos.toByteArray());代码解释:
- ByteArrayOutputStream: 一个字节数组输出流,可以用来在内存中构建数据。
- OutputStreamWriter: 一个字符流到字节流的桥梁,使用指定的字符集将写入的字符编码成字节。
- writer.write(): 将数据写入到 OutputStreamWriter,最终写入到 ByteArrayOutputStream。
- writer.flush(): 刷新缓冲区,确保所有数据都写入到输出流。
- ByteArrayInputStream: 一个字节数组输入流,可以用来从字节数组中读取数据。
- bos.toByteArray(): 将 ByteArrayOutputStream 中的数据转换为字节数组。
3. 上传到 FTP 服务器
现在我们有了 InputStream,可以使用 fileUpload 方法将其上传到 FTP 服务器。
private boolean fileUpload(InputStream isUploadFile, String dirName, String loggedInUser, String fileName){
boolean storeRetVal = false;
String fileType = fileName.substring(fileName.lastIndexOf(".") + 1, fileName.length());
storeRetVal = SISSFTPManager.getInstance().put(isUploadFile, dirName, fileName);
if (storeRetVal)
{
try {
if (fileType.trim().equalsIgnoreCase("csv")){
ICSAPI.getInstance().getSIMSOrderManager().createFileAudit(loggedInUser, fileName);
} else {
}
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SystemException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ApplicationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
logger.info("BulkUploadAction:fileUpload SFTP Transfer file successfully!");
} else {
logger.error("BulkUploadAction:fileUpload SFTP Transfer file FAILED!");
}
return storeRetVal;
}4. 调用示例
String dirName = "/ftp/upload/directory";
String loggedInUser = "user123";
String fileName = "PAYROLL_PRM.csv";
// 获取 InputStream (使用上面代码)
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try (Writer writer = new OutputStreamWriter(bos)) {
writer.write("Business,Position\n");
for (int i = 0; i < business.length; i++) {
writer.write(business[i] + "," + position[i] + "\n");
}
writer.flush();
} catch (IOException e) {
e.printStackTrace();
}
InputStream inputStream = new ByteArrayInputStream(bos.toByteArray());
boolean uploadSuccess = fileUpload(inputStream, dirName, loggedInUser, fileName);
if (uploadSuccess) {
System.out.println("File uploaded successfully!");
} else {
System.out.println("File upload failed!");
}注意事项:
- 确保正确处理 IOException,例如使用 try-catch 块。
- 在上传之前,可能需要设置 FTP 连接参数,例如服务器地址、端口号、用户名和密码。
- SISSFTPManager.getInstance().put() 的具体实现取决于所使用的 FTP 客户端库。常见的 Java FTP 客户端库包括 Apache Commons Net 和 JSch。 需要根据实际使用的库进行调整。
- 在关闭 writer 之前,务必调用 writer.flush(),以确保所有数据都写入到 ByteArrayOutputStream。
- 异常处理部分需要根据实际情况进行完善,添加更详细的错误信息和日志记录。
总结:
通过使用 ByteArrayOutputStream 和 ByteArrayInputStream,我们可以在内存中动态生成 CSV 数据流,并将其直接上传到 FTP 服务器,避免了不必要的磁盘 I/O 操作,从而提高了效率。 这种方法特别适用于需要快速生成和上传小文件的场景。 记住,要根据实际使用的 FTP 客户端库调整 fileUpload 方法的实现。










