文件IO

java.io.File是用于操作文件或目录的类:

File file = new File("hello.txt");

实例化File时不关心路径的目标并不会去读取文件或目录. File类提供了一些有用的方法:

  • isFile(): 判断路径指向的是否为文件

  • createNewFile(): 当路径指向的文件不存在时创建一个空文件

  • exists(): 判断路径指向的文件是否存在

  • delete(): 删除路径指向的文件或目录

  • length(): 返回文件的长度

  • isDirectory(): 判断路径指向的是否为目录

  • mkdir(): 根据路径创建空目录, 父目录必须存在

  • mkdirs(): 根据路径创建空目录, 会创建必要的父目录

  • list(): 以String[]类型返回目录中所有文件名

  • listFiles(): 以File[]类型返回目录中所有文件

字符流

Java使用流来读写文件, 字符流用来读写文本文件. 所有的字符流类都在java.io包中.

读取文本文件:

File file = new File("a.txt");
FileReader fin = new FileReader(file);
BufferedReader reader = new BufferedReader(fin);
try {
String str = reader.readLine();
System.out.println(str);
}
catch (IOException e) {
e.printStackTrace();
}
finally {
reader.close();
fin.close();
}

FileReader也可以直接用文件名创建. new FileReader("a.txt").

写入文本文件:

FileWriter fout = new FileWriter("a.txt", true);
BufferedWriter writer = new BufferedWriter(fout);
try {
String str = "Hello World";
writer.write(str);
}
catch (IOException e) {
e.printStackTrace();
}
finally {
writer.close();
fout.close();
}

FileWriter的第二个参数为append, true代表在文件尾追加, 默认false代表清空文件重写.

字节流

字节流用于读写二进制文件, 其读写的数据以byte[]类型存储.

所有字节流类都在java.io包中.

读取文件:

File file = new File("a.in");
FileInputStream fin = new FileInputStream(file);
Byte[] buf = new Byte[512]; try {
fin.read(buf);
}
catch {IOException e} {
e.printStackTrace();
}
finally {
fin.close();
}

写文件:

File file = new File("a.in");
FileOutputStream fout = new FileOutputStream(file);
Byte[] buf = new Byte[512];
try {
// write sth in buf
fin.write(buf);
}
catch {IOException e} {
e.printStackTrace();
}
finally {
fout.close();
}

标准输入输出

java.lang.System对象中维护了3个标准流, 用于终端输入输出:

  • System.out, 标准输出流, PrintStream对象
  • System.err: 标准错误流, PrintStream对象
  • System.in: 标准输入流, FileInputStream对象

在需要的时候我们可以将它们重定向到文件.

重定向标准输出:

File file = new File("a.out");
FileOutputStream fout = new FileOutputStream(file);
PrintStream pout = new PrintStream(fout);
PrintStream stdout = System.out; // save System.setOut(pout);
System.setOut(stdout); // recover

因为标准输入是字节流, 我们需要把它们转换成需要的类型才能使用:

int n;
byte[] buf = new byte[1024];
n = System.in.read(buf);
String s = new String(buf, 0, n);
System.out.println(s);

java.util.Scanner允许用迭代器的方式读取输入:

Scanner scanner = new Scanner(System.in);
while (scanner.hasNext()) {
// scanner.next(); // return Object
scanner.nextInt(); // return int
}

scanner可以直接将输入转换为内置类型使用很方便.

网络IO

TCP客户端

java.net.Socket是一个用作Tcp客户端的Socket. 从Socket中获得InputStreamOutputStream对象就可以与服务器通过Tcp连接通信了.

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket; public class TcpClient {
public static void main(String[] args) throws IOException { Socket client = new Socket("127.0.0.1", 5000);
client.setSoTimeout(10000); PrintStream out = new PrintStream(client.getOutputStream()); BufferedReader buf = new BufferedReader(new InputStreamReader(client.getInputStream())); String[] msgs = {"你好", "世界"}; for (String msg : msgs) {
out.println(msg); while (true) {
String echo = buf.readLine();
if (echo != null) {
System.out.println(echo);
break;
}
}
}
}
}

上述示例中发送完一条消息则进入轮询, 查看是否有服务端消息.

java.net.ServerSocket则是一个用作Tcp服务端的socket.

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList; public class TcpServer implements Runnable { private Socket client = null;
private String address; public TcpServer(Socket client) {
this.client = client;
} @Override
public void run() {
try {
String host = client.getInetAddress().toString();
String port = Integer.toString(client.getPort()); PrintStream out = new PrintStream(client.getOutputStream());
System.out.println("Get Connection");
BufferedReader buf = new BufferedReader(new InputStreamReader(client.getInputStream())); address = host + ":" + port;
System.out.println("get connection from" + address); while (true) { String str = buf.readLine();
if (str != null) {
out.println(str);
}
} } catch (Exception e) {
e.printStackTrace();
}
} public static void main(String[] args) {
ArrayList<Thread> list = new ArrayList<Thread>(); try {
ServerSocket socket = new ServerSocket(5000); while (true) {
// accept a new connection
Socket client = socket.accept();
Thread thread = new Thread(new TcpServer(client));
list.add(thread);
thread.start();
}
}
catch (IOException ioe) {
ioe.printStackTrace();
}
} }

上述示例是一个多线程服务器, ServerSocket监听5000端口. 当有客户端连接该端口时, socket.accept()将返回一个java.net.Socket对象.

创建一个线程持有Socket对象, 并与客户端进行通信.

UDP客户端

java.net.Datagram可以用作UDP客户端, 其接收到的数据报被封装为java.net.DatagramPacket.

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress; public class UdpClient {
public static void main(String[] args) throws IOException {
DatagramSocket socket = new DatagramSocket();
String[] msgs = {"1", "2.3", "520"};
for (String msg : msgs) {
byte[] buf = msg.getBytes();
InetAddress addr = InetAddress.getByName("127.0.0.1");
DatagramPacket packet = new DatagramPacket(buf, buf.length, addr, 5000);
socket.send(packet); while (true) {
byte[] recvBuf = new byte[256];
DatagramPacket recvPacket = new DatagramPacket(recvBuf, recvBuf.length);
socket.receive(recvPacket);
String echo = new String(recvPacket.getData(), 0, recvPacket.getLength());
if (echo != null) {
System.out.println(echo);
break;
}
}
}
} }

DatagramSocket的send方法用于发送数据报, receive用于接收数据报.

UDP服务器

import java.io.IOException;
import java.net.DatagramSocket;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.Socket;
import java.util.ArrayList;
import java.util.concurrent.atomic.AtomicInteger; public class UdpServer implements Runnable { private DatagramSocket socket = null;
private DatagramPacket packet = null;
private String address; public UdpServer(DatagramSocket socket, DatagramPacket packet) {
this.socket = socket;
this.packet = packet;
} @Override
public void run() {
try {
String msg = new String(packet.getData());
UdpServer.sum += Double.parseDouble(msg);
UdpServer.count += 1; int port = packet.getPort();
InetAddress address = packet.getAddress(); System.out.println("get msg from" + address); String response = new String(recvPacket.getData(), 0, recvPacket.getLength());
DatagramPacket sendPacket = new DatagramPacket(response.getBytes(), response.getBytes().length, address, port);
socket.send(sendPacket);
}
catch (IOException ioe) {
ioe.printStackTrace();
}
} public static void main(String[] args) {
AtomicInteger numThreads = new AtomicInteger(0);
ArrayList<Thread> list = new ArrayList<Thread>(); try {
DatagramSocket socket = new DatagramSocket(5000);
while (true) {
byte[] buf = new byte[100];
DatagramPacket packet = new DatagramPacket(buf, buf.length);
socket.receive(packet); Thread thread = new Thread(new UdpServer(socket, packet));
list.add(thread);
thread.start();
numThreads.incrementAndGet();
}
}
catch (IOException ioe) {
ioe.printStackTrace();
}
} }

因为UDP不需要维护连接, 服务端和客户端的socket是同样的.

上文是一个多线程UDP服务器, 不过所有线程持有同一个socket对象和要处理的数据报. 为了保证线程安全最好给socket加锁.

java.io与网络通信的更多相关文章

  1. Netty学习二:Java IO与序列化

    1 Java IO 1.1 Java IO 1.1.1 IO IO,即输入(Input)输出(Output)的简写,是描述计算机软硬件对二进制数据的传输.读写等操作的统称. 按照软硬件可分为: 磁盘I ...

  2. JAVA基础知识之IO——Java IO体系及常用类

    Java IO体系 个人觉得可以用"字节流操作类和字符流操作类组成了Java IO体系"来高度概括Java IO体系. 借用几张网络图片来说明(图片来自 http://blog.c ...

  3. 《安卓网络编程》之第二篇 java环境下网络通信的综合应用

    经过前面内容的学习,我们了解了Java技术中实现网络通信的基本知识.下面将通过一个具体视力的实现过程,讲解客户端和服务器端通信的流程. 服务器端的实现文件是 Server.java,代码如下: imp ...

  4. BATJ面试必会之Java IO 篇

    一.概览 二.磁盘操作 三.字节操作 实现文件复制 装饰者模式 四.字符操作 编码与解码 String 的编码方式 Reader 与 Writer 实现逐行输出文本文件的内容 五.对象操作 序列化 S ...

  5. java IO流 对文件操作的代码集合

    Io流 按照分类 有两种分类 流向方向: 有输入流和输出流 按照操作类型有:字节流和字符流 按照流向方向 字节流的一些操作 //读文件 FileInputStream fis = new FileIn ...

  6. java IO流知识点总结

    I/O类库中使用“流”这个抽象概念.Java对设备中数据的操作是通过流的方式.表示任何有能力产出数据的数据源对象,或者是有能力接受数据的接收端对象.“流”屏蔽了实际的I/O设备中处理数据的细节.IO流 ...

  7. Java回顾之网络通信

    在这篇文章里,我们主要讨论如何使用Java实现网络通信,包括TCP通信.UDP通信.多播以及NIO. TCP连接 TCP的基础是Socket,在TCP连接中,我们会使用ServerSocket和Soc ...

  8. 高级Java工程师必备 ----- 深入分析 Java IO (二)NIO

    接着上一篇文章 高级Java工程师必备 ----- 深入分析 Java IO (一)BIO,我们来讲讲NIO 多路复用IO模型 场景描述 一个餐厅同时有100位客人到店,当然到店后第一件要做的事情就是 ...

  9. java IO(BIO)、NIO、AIO

    IO 服务端ServerSocket 客户端Socket 缺点每次客户端建立连接都会另外启一个线程处理.读取和发送数据都是阻塞式的. 如果1000个客户端建立连接将会产生1000个线程 Server端 ...

随机推荐

  1. xml概述(1)

    本节要点: 标记语言的定义 XML简介 XML与HTML 比较 XML与数据库比较 XML的特点 XML结构 1 标记语言的定义 "XML.SGML.HTML"中的"ML ...

  2. Sql去重

    distinct:用于返回唯一不同的值. 注意:1.语句中select显示的字段只能是distinct指定的字段,其他字段是不可能出现的. 2.distinct必须放在开头 如select disti ...

  3. ES6数组及数组方法

    ES6数组可以支持下面的几种写法: (1)var [a,b,c] = [1,2,3]; (2)var [a,[[b],c]] = [1,[[2],3]]; (3)let [x,,y] = [1,2,3 ...

  4. ES6的数据类型

    首先ES6包含了ES5里面的数据类型,有undefined,null,boolean,String,Number,Object,而ES6又新增了一种数据类型是Symbol,这种的Symbol数据类型是 ...

  5. 第四节:dingo/API 最新版 V2.0 之 Responses (连载)

    因为某些某些原因,不能按时更新,唉.我会尽力,加快速度.(这句话不是翻译的哈) 原文地址--> https://github.com/dingo/api/wiki/Responses A fun ...

  6. php中static 静态关键字

    一直依赖对于php中static关键字比较模糊,只是在单例模式中用过几次.上网查了查,没有找到很全的介绍,自己总结一下. 根据使用位置分为两部分 1.函数体中的静态变量 2.类中的静态属性和方法 1 ...

  7. scala写算法-快排

    快排算法很经典,今天用scala的函数式思维来整理一下并实现: def qsort(list: List[Int]):List[Int]=list match { case Nil=>Nil c ...

  8. Nginx的 HTTP 499 状态码处理

    1.前言 今天在处理一个客户问题,遇到Nginx access log中出现大量的499状态码.实际场景是:客户的域名通过cname解析到我们的Nginx反向代理集群上来,客户的Web服务是由一个负载 ...

  9. 6.Nginx作为负载均衡服务器应用

    案例:Nginx作为负载均衡服务器应用 nginx的负载均衡功能是通过upstream命令实现的,因此他的负载均衡机制比较简单,是一个基于内容和应用的7层交换负载均衡的实现.Nginx负载均衡默认对后 ...

  10. android的ADK下载地址

    把下面所有的包下载到temp目录下进行安装. 用代理http://ppdaili.com/https://dl-ssl.google.com/android/repository/repository ...