Java使用FileInputStream&&FileOutputStream模拟客户端向服务器端上传文件(单线程)

客户端代码
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

public class Client {
    public static void main(String[] args) throws Exception {
        //创建客户端对象,指定服务器端IP和端口号(host是服务器名称或IP地址,port是端口号)
        Socket client = new Socket("192.168.0.100", 8973);
        //使用socket中的方法创建输出流对象,向服务器端传送数据
        OutputStream outputStream = client.getOutputStream();

        //读取本地数据写进输出流中,传送给服务器端
        //创建输入流,关联数据源文件
        FileInputStream fileInputStream = new FileInputStream("client.txt");
        int len;
        byte[] bytes = new byte[8192];
        while ((len = fileInputStream.read(bytes)) != -1) {
            outputStream.write(bytes, 0, len);
        }

        //解决阻塞问题
        client.shutdownOutput();

        //创建输入流,获取服务器端传送回来的回执信息并且打印
        InputStream inputStream = client.getInputStream();
        while ((len = inputStream.read(bytes)) != -1){
            System.out.println(new String(bytes,0,len));
        }

        //关闭流
        client.close();
        outputStream.close();
        inputStream.close();
    }
}

服务器端
public class Server {
    public static void main(String[] args) throws Exception{
        //创建服务器端对象,指定服务器使用的端口号
        ServerSocket server = new ServerSocket(8973);
        //使用accpet方法接收客户端发送来的数据
        Socket accpet = server.accept();
        //使用socket中的方法创建输入流对象,获取客户端发送来的数据
        InputStream inputStream = accpet.getInputStream();

        //将客户端发送来的数据写入到服务器端的本地文件中
        //创建输出流,关联目的地文件
        FileOutputStream fileOutputStream = new FileOutputStream("server.txt");
        int len;
        byte[] bytes= new byte[8192];
        while((len = inputStream.read(bytes))!= -1){
            fileOutputStream.write(bytes,0,len);
        }

        //创建输出流,给客户端发送回执信息
        OutputStream outputStream = accpet.getOutputStream();
        outputStream.write("文件上传成功".getBytes());

        //关闭流
        //实际开发中,不会关闭服务器端的Socket对象
        accpet.close();
        outputStream.close();
    }
}

细节1:应该先启动服务器端,再启动客户端

细节2:client.shutdownOutput()方法是解决线程阻塞问题. 客户端while()循环中的结束条件为不等于-1,所以会发送结束符之前的信息.服务器端在接收数据进行while()循环读取的时候读取不到结束符,所以会一直运行陷入死循环.我们使用shutdownOutput()方法加入一个结束符,可以解决这个问题.

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java 中可以使用多线程实现文件拆分、操作、合并的过程。具体步骤如下: 1. 将原始文件按照指定大小进行拆分,每个拆分出来的文件都可以在单独的线程中进行操作。 2. 在每个线程中对拆分出来的文件进行处理,可以使用 FileChannel 进行文件读写操作。 3. 等待所有线程完成操作后,将处理好的文件再次进行合并。 示例代码如下: ```java import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; public class FileSplitAndMerge { private static final int FILE_SIZE = 1024 * 1024 * 10; // 拆分文件大小为 10MB private static final String FILE_PATH = "test.txt"; // 原始文件路径 private static final String SPLIT_PATH = "split/"; // 拆分文件存放路径 private static final String MERGE_PATH = "merge/"; // 合并文件存放路径 private static final String MERGE_FILE_NAME = "merge.txt"; // 合并后的文件名 public static void main(String[] args) { // 拆分文件 splitFile(); // 操作拆分出来的文件 operateSplitFiles(); // 合并文件 mergeFile(); } /** * 拆分文件 */ private static void splitFile() { File file = new File(FILE_PATH); if (!file.exists()) { return; } File splitDir = new File(SPLIT_PATH); if (!splitDir.exists()) { splitDir.mkdirs(); } try (FileChannel channel = new FileInputStream(file).getChannel()) { long fileSize = file.length(); long position = 0; while (position < fileSize) { long remaining = fileSize - position; long size = Math.min(remaining, FILE_SIZE); String fileName = String.format("%s.%03d", file.getName(), position / FILE_SIZE + 1); File splitFile = new File(splitDir, fileName); try (FileChannel outChannel = new FileOutputStream(splitFile).getChannel()) { channel.transferTo(position, size, outChannel); } position += size; } } catch (IOException e) { e.printStackTrace(); } } /** * 操作拆分出来的文件 */ private static void operateSplitFiles() { File splitDir = new File(SPLIT_PATH); if (!splitDir.exists()) { return; } for (File splitFile : splitDir.listFiles()) { new Thread(() -> { try (FileChannel channel = new FileInputStream(splitFile).getChannel()) { ByteBuffer buffer = ByteBuffer.allocate(1024); while (channel.read(buffer) != -1) { buffer.flip(); // TODO: 对文件进行操作,例如统计字符数等 buffer.clear(); } } catch (IOException e) { e.printStackTrace(); } }).start(); } } /** * 合并文件 */ private static void mergeFile() { File splitDir = new File(SPLIT_PATH); if (!splitDir.exists()) { return; } File mergeDir = new File(MERGE_PATH); if (!mergeDir.exists()) { mergeDir.mkdirs(); } try (FileChannel outChannel = new FileOutputStream(new File(mergeDir, MERGE_FILE_NAME)).getChannel()) { for (File splitFile : splitDir.listFiles()) { try (FileChannel channel = new FileInputStream(splitFile).getChannel()) { channel.transferTo(0, channel.size(), outChannel); } } } catch (IOException e) { e.printStackTrace(); } } } ``` 该示例代码中,首先将原始文件按照指定大小进行拆分,并将拆分出来的文件存放到指定的目录中。然后,对每个拆分出来的文件开启一个线程进行操作,可以在 `operateSplitFiles` 方法中编写相应的操作代码。最后,将处理好的文件进行合并,将合并后的文件存放到指定的目录中。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值