2018-07-20


今日学习

  • IO操作
  • java&XML
  • Socket

二:IO操作

  • 基本功能:读和写
  • 字节流:以“Stream”结尾;可以处理所有类型的数据,在读取时,读到一个字节就返回一个字节。
  • 字符流:以“Reader”或“Writer”结尾;仅能处理纯文本数据,在读取时,速到一个或多个字节,先查找指定的编码表,然后将查到的字符返回。

|/ | 字节流 | 字符流 | |–|–|–| | 输入流 | InputStream | Reader | | 输出流 | OutputStream | Writer |

字节流(Stream)

  • DataInputStream 和 DataOutputStream 可以以二进制格式读写所有的基本 Java 类型。
  • FileInputStream 和 FileOutputStream 可以提供附着在一个磁盘文件上的输入流和输出流,而你只需向其构造器提供文件名或文件的完整路径名。
  • BufferedInputStream(InputStream in)
    创建一个带缓冲区的流。带缓冲区的输入流在从流中读入字符时,不会每次都对设备访问。当缓冲区为空时,会向缓冲区中读入一个新的数据块。
  • BufferedOutputStream(OutputStream out) 创建一个带缓冲区的流。带缓冲区的输出流在收集要写出的字符时,不会每次都对设备访问。当缓冲区填满或当流被冲刷(flush)时,数据就被写出。 流在默认情况下是不被缓冲区缓存的,如果想使用缓冲机制,以及用于文件的数据输入方法,那么必须要用到以下构造器序列:
DataInputStream din = new DateInputStream(
    new BufferedInputStream(
     new FileInputStream("filename.txt")));

把 DataInputStream 置于构造器链的最后,这是因为我们希望使用DataInputStream 的方法,并且希望它们能够使用带缓冲机制的 read 方法。 - PushbackInputStream(InputStream in)
PushbackInputStream(InputStream in, int size) 构建一个可以预览一个字节或者具有指定尺寸的回推缓冲区的流。 当读入输入时,你经常需要浏览下一个字节,以了解它是否是你想要的值:

PushbackInputStream pbin = new PushbackInputStream(
    new BufferedInputStream(
        new FileInputStream("filename.txt")));
// 预读下一个字节
int b = pbin.read();
// 在它非你所期望的值时将其推回流中
if (b != "<") pbin.unread(b);

能够预先浏览并且还可以读入数字,那么就需要一个既是可回推输入流,又是一个数据输入流的引用。

DataInputStream din = new DataInputStream(
 new PushbackInputStream(
    new BufferedInputStream(
        new FileInputStream("filename.txt"))));

字符流(Reader/Writer)

  • OutputStreamWriter 将使用选定的字符编码方式,把 Unicode 字符流转换为字节流
  • InputStreamReader 将包含字节(用某种字符编码方式表示的字符)的输入流转换为可以产生 Unicode 码元的读入器。
// 让一个输入读入器可以从控制台读入键盘敲击信息,并将其转换为 Unicode
InputStreamReader in = new InputStreamReader(System.in);
// 通过在 InputStreamReader 的构造器中进行指定的方式来选择不同的编码方式
InputStreamReader inr = new InputStreamReader(new FileInputStream(), "ISO08859_5");
  • PrintWriter:以文本格式写出数据,有自动的flush功能

拥有以文本格式打印字符串和数字的方法,它甚至还有一个将 PrintWriter 链接到 FileWriter 的便捷方法:

PrintWriter out = new PrintWriter("filename.txt");
String name = "Harry Hacker";
// 写入文件
out.print(name);
out.println(name);
  • PrintWriter(OutputStream out) 根据现有的OutputStream创建不带自动刷新的PrintWriter
  • PrintWriter(Writer out) 创建不带自动刷新的PrintWriter
  • BufferedReader:处理文本输入,BufferedReader 没有任何用于读入数字的方法
BufferedReader in = new BufferedReader(
    new InputStreamReader(
        new FileInputStream("filename.txt","UTF-8"));

建议使用Scanner来读入文本输入

随机访问文件

  • RandomAccessFile:可以在文件中的任何位置查找或写入数据 随机访问文件有一个表示下一个将被读入或写出的字节所处位置的文件指针,seek 方法可以将这个文件指针设置到文件中的任意字节位置,seek 的参数是一个 long 类型的整数,它的值位于 0 到文件按照字节来度量的长度之间。
    • getFilePointer 方法将返回文件指针的当前位置。
class WriteFile extends Thread{
    int block;
    File file;
    int L = 100;
    WriteFile(File file, int block){
        this.file = file;
        this.block = block;
    }
    @Override
    public void run() {
        try {
            RandomAccessFile raf = new RandomAccessFile(file, "rw");
            raf.seek((block-1)*L);
            raf.writeBytes("This is block"+block);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
public class RandomAccessFileDemo {
    static File file = new File("test.txt");
    public static void main(String [] args){
        // 写入
// if (file.exists()){
// file.delete();
// }
//
// // 严格按照指定的block顺序写的,与线程创建的顺序无关
// new WriteFile(file,1).start();
// new WriteFile(file,2).start();
// new WriteFile(file,3).start();
// new WriteFile(file,4).start();
// new WriteFile(file,5).start();
// new WriteFile(file,6).start();
        //读取
        try {
            RandomAccessFile read = new RandomAccessFile(file,"r");
            read.seek(500);
            byte [] str = new byte[20];
            read.read(str);
            String in = new String(str);
            System.out.println(in);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Apache Commons IO

  • maven 配置:
        <!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.6</version>
        </dependency>
public class ApacheIODemo {
    public static void main(String [] args){
        File file = new File("test.txt");
        File file2 = new File("text_new.txt");
        try {
            // String input = FileUtils.readFileToString(file, "UTF-8");
            // System.out.println(input);
            FileUtils.copyFile(file,file2);

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

一:XML操作

语法规则

  • 省略关闭标签是非法的,所有元素都必须有关闭标签
  • XML标签对大小写敏感
  • XML必须正确嵌套
  • XML文档必须有根元素
  • XML属性值要加引号
  • 空格会被保留

用java读取XML数据

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
... ...
public class XMLDemo {
    public static void main(String [] args){
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        try {
            //DOM
            DocumentBuilder builder = factory.newDocumentBuilder();
            Document document = builder.parse(new File("languages.xml"));
            Element root = document.getDocumentElement();
            System.out.println("cat="+root.getAttribute("cat"));
            NodeList list = root.getElementsByTagName("lan");
            for (int i=0;i<list.getLength();i++){
                Element lan = (Element) list.item(i);
                System.out.println("----------------");
                System.out.println("id="+lan.getAttribute("id"));
                //不建议采用
                // Element name = (Element) lan.getElementsByTagName("name").item(0);
                // System.out.println("name="+name.getTextContent());
                NodeList child = lan.getChildNodes();
                for (int j =0; j<child.getLength();j++){
                    Node c =child.item(j);
                    // 除去不可见的节点
                    if (c instanceof Element) {
                        System.out.println(c.getNodeName() + "=" + c.getTextContent());
                    }
                }
            }
        } catch (ParserConfigurationException e) {
            e.printStackTrace();
        } catch (SAXException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

写XML

import org.w3c.dom.Document;
import org.w3c.dom.Element;
... ...
public class CreateXMLDemo {
    public static void main(String [] args){
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        try {
            // DOM
            DocumentBuilder builder = factory.newDocumentBuilder();
            Document document = builder.newDocument();
            Element root = document.createElement("languages");
            root.setAttribute("cat","it");

            Element lan1 = document.createElement("lan");
            lan1.setAttribute("id","1");
            Element name1 = document.createElement("name");
            name1.setTextContent("java");
            Element ide1 = document.createElement("ide");
            ide1.setTextContent("Eclipse");
            lan1.appendChild(name1);
            lan1.appendChild(ide1);

            root.appendChild(lan1);
            document.appendChild(root);

            // 将XML转换成字符串
            TransformerFactory transformerFactory = TransformerFactory.newInstance();
            try {
                Transformer transformer = transformerFactory.newTransformer();
                StringWriter writer = new StringWriter();
                transformer.transform(new DOMSource(document),new StreamResult(writer));
                System.out.println(writer.toString());

                transformer.transform(new DOMSource(document), new StreamResult(new File("newXML.xml")));
            } catch (TransformerConfigurationException e) {
                e.printStackTrace();
            } catch (TransformerException e) {
                e.printStackTrace();
            }
        } catch (ParserConfigurationException e) {
            e.printStackTrace();
        }
    }
}

dom4j

  • maven 配置
       <dependency>
            <groupId>dom4j</groupId>
            <artifactId>dom4j</artifactId>
            <version>1.6.1</version>
        </dependency>

        <dependency>
            <groupId>jaxen</groupId>
            <artifactId>jaxen</artifactId>
            <version>1.1.6</version>
        </dependency>
  • 写XML
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
public class Dom4jDemo {
    public static void main(String [] args){
        String xmlString = "<root><people>Alice</people></root>";
        try {
            Document document = DocumentHelper.parseText(xmlString);
            System.out.println(document.asXML());
        } catch (DocumentException e) {
            e.printStackTrace();
        }
    }
}

Socket通信

TCP

  • 客户端
public class TCPClientDemo {
    public static void main (String[] args){
        try {
            Socket s = new Socket("127.0.0.1",12345);
            OutputStream os = s.getOutputStream();
            DataOutputStream dos = new DataOutputStream(os);
            dos.writeUTF("Hello,server!");
            InputStream is = s.getInputStream();
            DataInputStream dis = new DataInputStream (is);
            System.out.println(dis.readUTF());
            dos.flush();
            dos.close();
            dis.close();
            s.close();
        }catch(ConnectException connExc){
            System.out.println("连接失败!");
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch(IOException e){
            e.printStackTrace();
        }
    }
}
  • 服务端
public class TCPServerDemo {
    public static void main(String [] args){
        try{
            ServerSocket ss = new ServerSocket(12345);
            while(true){
                Socket s = ss.accept();
                System.out.println("connected!");
                DataInputStream dis = new DataInputStream(s.getInputStream());
                System.out.println(dis.readUTF());
                OutputStream os = s.getOutputStream();
                DataOutputStream dos = new DataOutputStream (os);
                dos.writeUTF("Hello , "+s.getInetAddress()+" ports "+s.getPort());
                dis.close();
                dos.close();
                s.close();
                System.out.println("closed!");
            }
        }catch(IOException e){
            e.printStackTrace();
            System.out.println("程序运行错误:"+e);
        }
    }
}

java.net.SocketException: socket closed 解决方式

想边发送边接受最正确的方式就是发送和接受的操作都做完之后再一起关闭IO流,即socket.getInputStream() 和 socket.getOutputStream() 在使用过程中,不能关闭,否则会抛出这个异常。