1.对象流的使用
1.ObjectInputStream和ObjectOutputStream 2.作用:用于存储和读取基本数据类型的数据和对象的处理流。它的强大之处就是可以把java中的对象写入到数据源中,也能把对象从数据源中还原回来。 3.要想一个java对象是可序列化的,需要满足相应的条件,见Person.java 4.序列化机制: 对象序列化机制允许把内存中的Java对象转换成平台无关的二进制流,从而允许把这种 二进制流持久地保存在磁盘上,或通过网络将这种二进制流传输到另一个网络节点。 当其它程序获取了这种二进制流,就可以恢复成原来的Java对象。
/*
Person需要满足以下的要求,才可以进行序列化
1.需要实现接口:实现Serializable
2.当前类提供一个全局常量:serialVersionUID
3.除了当前类需要实现Serializabel接口外,还必须保证其内部所有属性也必须是可序列化的
(默认情况下,基本数据类型可序列化)
补充:ObjectOutputStream和ObjectInputStream不能序列化static和transient修饰的成员变量
*/
public class Person implements Serializable {
private int id;
private int age;
private String name;
private Account account;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"id=" + id +
", age=" + age +
", name='" + name + '\'' +
", account=" + account +
'}';
}
private static final long serialVersionUID = 989439L;
public Person(){}
public Person(int id,int age, String name) {
this.id = id;
this.age = age;
this.name = name;
}
public Person(String name,int age,int id, Account account) {
this.id = id;
this.age = age;
this.name = name;
this.account = account;
}
}
class Account implements Serializable {
public static final long serialVersionUID = 4754534532L;
private double balance;
@Override
public String toString() {
return "Account{" +
"balance=" + balance +
'}';
}
public double getBalance() {
return balance;
}
public void setBalance(double balance) {
this.balance = balance;
}
public Account(double balance) {
this.balance = balance;
}
}
2.Files工具类的使用:操作文件或目录的工具类
@Test
public void test1() throws IOException{
Path path1 = Paths.get("d:\\nio", "hello.txt");
Path path2 = Paths.get("bao.txt");
// Path copy(Path src, Path dest, CopyOption … how) : 文件的复制
//要想复制成功,要求path1对应的物理上的文件存在。path1对应的文件没有要求。
// Files.copy(path1, path2, StandardCopyOption.REPLACE_EXISTING);
// Path createDirectory(Path path, FileAttribute<?> … attr) : 创建一个目录
//要想执行成功,要求path对应的物理上的文件目录不存在。一旦存在,抛出异常。
Path path3 = Paths.get("d:\\nio\\nio1");
// Files.createDirectory(path3);
// Path createFile(Path path, FileAttribute<?> … arr) : 创建一个文件
//要想执行成功,要求path对应的物理上的文件不存在。一旦存在,抛出异常。
Path path4 = Paths.get("d:\\nio\\hi.txt");
// Files.createFile(path4);
// void delete(Path path) : 删除一个文件/目录,如果不存在,执行报错
// Files.delete(path4);
// void deleteIfExists(Path path) : Path对应的文件/目录如果存在,执行删除.如果不存在,正常执行结束
Files.deleteIfExists(path3);
// Path move(Path src, Path dest, CopyOption…how) : 将 src 移动到 dest 位置
//要想执行成功,src对应的物理上的文件需要存在,dest对应的文件没有要求。
// Files.move(path1, path2, StandardCopyOption.ATOMIC_MOVE);
// long size(Path path) : 返回 path 指定文件的大小
long size = Files.size(path2);
System.out.println(size);
}
@Test
public void test2() throws IOException{
Path path1 = Paths.get("d:\\nio", "hello.txt");
Path path2 = Paths.get("atguigu.txt");
// boolean exists(Path path, LinkOption … opts) : 判断文件是否存在
System.out.println(Files.exists(path2, LinkOption.NOFOLLOW_LINKS));
// boolean isDirectory(Path path, LinkOption … opts) : 判断是否是目录
//不要求此path对应的物理文件存在。
System.out.println(Files.isDirectory(path1, LinkOption.NOFOLLOW_LINKS));
// boolean isRegularFile(Path path, LinkOption … opts) : 判断是否是文件
// boolean isHidden(Path path) : 判断是否是隐藏文件
//要求此path对应的物理上的文件需要存在。才可判断是否隐藏。否则,抛异常。
// System.out.println(Files.isHidden(path1));
// boolean isReadable(Path path) : 判断文件是否可读
System.out.println(Files.isReadable(path1));
// boolean isWritable(Path path) : 判断文件是否可写
System.out.println(Files.isWritable(path1));
// boolean notExists(Path path, LinkOption … opts) : 判断文件是否不存在
System.out.println(Files.notExists(path1, LinkOption.NOFOLLOW_LINKS));
}
/**
* StandardOpenOption.READ:表示对应的Channel是可读的。
* StandardOpenOption.WRITE:表示对应的Channel是可写的。
* StandardOpenOption.CREATE:如果要写出的文件不存在,则创建。如果存在,忽略
* StandardOpenOption.CREATE_NEW:如果要写出的文件不存在,则创建。如果存在,抛异常
*
* @author shkstart 邮箱:shkstart@126.com
* @throws IOException
*/
@Test
public void test3() throws IOException {
Path path1 = Paths.get("d:\\nio", "hello.txt");
// InputStream newInputStream(Path path, OpenOption…how):获取 InputStream 对象
InputStream inputStream = Files.newInputStream(path1, StandardOpenOption.READ);
// OutputStream newOutputStream(Path path, OpenOption…how) : 获取 OutputStream 对象
OutputStream outputStream = Files.newOutputStream(path1, StandardOpenOption.WRITE,StandardOpenOption.CREATE);
// SeekableByteChannel newByteChannel(Path path, OpenOption…how) : 获取与指定文件的连接,how 指定打开方式。
SeekableByteChannel channel = Files.newByteChannel(path1, StandardOpenOption.READ,StandardOpenOption.WRITE,StandardOpenOption.CREATE);
// DirectoryStream<Path> newDirectoryStream(Path path) : 打开 path 指定的目录
Path path2 = Paths.get("e:\\teach");
DirectoryStream<Path> directoryStream = Files.newDirectoryStream(path2);
Iterator<Path> iterator = directoryStream.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
}
3.RandomAccessFile的使用
1.RandomAccessFile直接继承于java.lang.Object类,实现了DataInput和DataOutput接口
-
2.RandomAccessFile既可以作为一个输入流,又可以作为一个输出流 *
-
3.如果RandomAccessFile作为输出流时,写出到的文件如果不存在,则在执行过程中自动创建。
-
如果写出到的文件存在,则会对原有文件内容进行覆盖。(默认情况下,从头覆盖) *
-
可以通过相关的操作,实现RandomAccessFile“插入”数据的效果
-
@Test
public void test1() {
RandomAccessFile raf1 = null;
RandomAccessFile raf2 = null;
try {
//1.
raf1 = new RandomAccessFile(new File("爱情与友情.jpg"),"r");
raf2 = new RandomAccessFile(new File("爱情与友情1.jpg"),"rw");
//2.
byte[] buffer = new byte[1024];
int len;
while((len = raf1.read(buffer)) != -1){
raf2.write(buffer,0,len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//3.
if(raf1 != null){
try {
raf1.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(raf2 != null){
try {
raf2.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
@Test
public void test2() throws IOException {
RandomAccessFile raf1 = new RandomAccessFile("hello.txt","rw");
raf1.seek(3);//将指针调到角标为3的位置
raf1.write("xyz".getBytes());//
raf1.close();
}
/*
使用RandomAccessFile实现数据的插入效果
*/
@Test
public void test3() throws IOException {
RandomAccessFile raf1 = new RandomAccessFile("hello.txt","rw");
raf1.seek(3);//将指针调到角标为3的位置
//保存指针3后面的所有数据到StringBuilder中
StringBuilder builder = new StringBuilder((int) new File("hello.txt").length());
byte[] buffer = new byte[20];
int len;
while((len = raf1.read(buffer)) != -1){
builder.append(new String(buffer,0,len)) ;
}
//调回指针,写入“xyz”
raf1.seek(3);
raf1.write("xyz".getBytes());
//将StringBuilder中的数据写入到文件中
raf1.write(builder.toString().getBytes());
raf1.close();
//思考:将StringBuilder替换为ByteArrayOutputStream
}
4.网络编程
一、网络编程中有两个主要的问题:
-
1.如何准确地定位网络上一台或多台主机;定位主机上的特定的应用
-
2.找到主机后如何可靠高效地进行数据传输 *
-
二、网络编程中的两个要素:
-
1.对应问题一:IP和端口号
-
2.对应问题二:提供网络通信协议:TCP/IP参考模型(应用层、传输层、网络层、物理+数据链路层) * *
-
三、通信要素一:IP和端口号 *
-
IP:唯一的标识 Internet 上的计算机(通信实体)
-
-
在Java中使用InetAddress类代表IP
-
-
IP分类:IPv4 和 IPv6 ; 万维网 和 局域网
-
-
本地回路地址:127.0.0.1 对应着:localhost *
-
-
如何实例化InetAddress:两个方法:getByName(String host) 、 getLocalHost()
-
-
两个常用方法:getHostName() / getHostAddress() *
-
端口号:正在计算机上运行的进程。
-
-
要求:不同的进程有不同的端口号
-
范围:被规定为一个 16 位的整数 0~65535。 *
-
端口号与IP地址的组合得出一个网络套接字:Socket
-
-