LineNumberInputStream и StringBufferInputStream официально не рекомендуется больше использовать, вместо них рекомендуется использовать LineNumberReader и StringReader.
ByteArrayInputStream и ByteArrayOutputStream
Массивы байтов обрабатывают потоки, создают в памяти буфер для использования в качестве потока и считывают данные из буфера быстрее, чем с носителя (например, с диска).
//用ByteArrayOutputStream暂时缓存来自其他渠道的数据
ByteArrayOutputStream data = new ByteArrayOutputStream(1024); //1024字节大小的缓存区
data.write(System.in.read()); // 暂存用户输入数据
//将data转为ByteArrayInputStream
ByteArrayInputStream in = new ByteArrayInputStream(data.toByteArray());
FileInputStream и FileOutputStream
Получите доступ к файлу, используйте файл как InputStream и реализуйте операции чтения и записи в файле.
ObjectInputStream и ObjectOutputStream
Поток объектов, конструктор должен передавать поток для чтения и записи объектов JAVA; его можно использовать для сериализации, а объект должен реализовать интерфейс Serializable.
//java对象的写入
FileOutputStream fileStream = new FileOutputStream("example.txt");
ObjectOutputStream out = new ObjectOutputStream(fileStream);
Example example = new Example();
out.writeObject(example);
//java对象的读取
FileInputStream fileStream = new FileInputStream("example.txt");
ObjectInputStream in = new ObjectInputStream(fileStream);
Example = (Example) in.readObject();
PipedInputStream и PipedOutputStream
Конвейерный поток, подходящий для передачи данных между двумя потоками, один поток отправляет данные через выходной поток конвейера, а другой поток считывает данные через входной поток конвейера для реализации обмена данными между двумя потоками.
Объединяет несколько потоков ввода в один поток ввода, позволяя приложениям последовательно объединять несколько потоков ввода.
InputStream in1 = new FileInputStream("example1.txt");
InputStream in2 = new FileInputStream("example2.txt");
SequenceInputStream sequenceInputStream = new SequenceInputStream(in1, in2);
//数据读取
int data = sequenceInputStream.read();
FilterInputStream и FilterOutputStream используют шаблон декоратора для добавления дополнительных функций к потоку.Параметры построения подкласса требуют InputStream/OutputStream
ByteArrayOutputStream out = new ByteArrayOutputStream(2014);
//数据写入,使用DataOutputStream装饰一个InputStream
//使用InputStream具有对基本数据的处理能力
DataOutputStream dataOut = new DataOutputStream(out);
dataOut.writeDouble(1.0);
//数据读取
ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
DataInputStream dataIn = new DataInputStream(in);
Double data = dataIn.readDouble();
DataInputStream и DataOutputStream (подклассы потока Filter)
Добавляет возможность обработки различных базовых типов данных для других потоков, таких как byte, int, String.
BufferedInputStream и BufferedOutputStream (подклассы потока Filter)
Добавить буферизацию для других потоков
PushBackInputStream (подкласс FilterInputStream)
Оттолкните входной поток, вы можете перемотать некоторые данные, прочитанные в буфер входного потока.
PrintStream (подкласс FilterOutputStream)
Поток печати, аналогичный System.out.print
2 символьный поток JAVA.IO
21.png
Из направленного графа потока байтов и потока символов они соответствуют друг другу, например CharArrayReader и ByteArrayInputStream.
Преобразование потока байтов и потока символов: InputStreamReader может преобразовывать InputStream в Reader, OutputStreamReader может преобразовывать OutputStream в Writer.
//InputStream转为Reader
InputStream inputStream = new ByteArrayInputStream("程序".getBytes());
InputStreamReader reader = new InputStreamReader(inputStream, StandardCharsets.UTF_8);
//OutputStream转为Writer
OutputStream out = new FileOutputStream("example.txt");
OutputStreamWriter writer = new OutputStreamWriter(out);
//以字符为单位读写
writer.write(reader.read(new char[2]));
Отличие: единицей чтения потока байтов являются байты, а единицей чтения потока символов — символы; символ состоит из байтов, например кодировка с переменной длиной слова UTF-8 представлена 1~4 байтами.
3 искаженных персонажа и поток символов
Символы представлены разными кодировками, и их длина в байтах (длина слова) различна. Например, формат кодировки utf-8 слова «Cheng» состоит из [-25][-88][-117]. Кодировка ISO_8859_1 представляет собой один байт [63].
Обычно работа ресурсов в работе ориентирована на потоки байтов, однако при преобразовании ресурсов данных в байты по разным байт-кодам их содержимое различается, что легко приводит к искажению символов.
Два искаженных сценария
Кодировка символов, используемая кодированием и декодированием, несовместима: ресурс закодирован в UTF-8, но открывается с использованием декодирования GBK в коде.
Использование потока байтов для чтения количества байтов не соответствует указанной длине слова символа: символ состоит из байтов, например, формат utf-8 «cheng» составляет три байта; если он читается каждые два байта в InputStream Возьмите поток, а затем преобразуйте его в String (кодировка java по умолчанию — utf-8), тогда будут искаженные символы (наполовину китайские, угадайте что)
ByteArrayInputStream in = new ByteArrayInputStream("程序大法好".getBytes());
byte[] buf = new byte[2]; //读取流的两个字节
in.read(buf); //读取数据
System.out.println(new String(buf)); //乱码
---result----
� //乱码
Искаженная сцена 1, если вы знаете кодировку символов ресурса, вы можете использовать соответствующую кодировку символов для декодирования и решения проблемы.
искаженная сцена 2,Все байты могут быть прочитаны за один раз, а затем закодированы за один раз. Но для больших файловых потоков это нереально, отсюда и появление символьных потоков
Поток байтов преобразуется в поток символов с помощью InputStreamReader и OutputStreamReader, в которых может быть указана кодировка символов, а затем обрабатывается в единицах символов, что может решить искаженные символы.
InputStreamReader reader =
new InputStreamReader(inputStream, StandardCharsets.UTF_8);
4 Концептуальное различие между набором символов и кодировкой символов
Связь между набором символов и кодировкой символов, набор символов — это спецификация, а кодировка символов — это конкретная реализация спецификации.;Набор символов определяет уникальное соответствие между символами и значениями двоичного кода, но не определяет конкретный метод хранения;
unicode, ASCII, GB2312, GBK — все это наборы символов;Среди них ASCII, GB2312 и GBK являются как наборами символов, так и кодировками; будьте осторожны, чтобы не перепутать разницу между ними.; А конкретная реализация юникода это UTF-8, UTF-16, UTF-32
Самый ранний код ASCII использовал один байт (8 бит) для указания отношения отображения между символами и двоичным кодом.Стандартный код ASCII определяет 128 символов, что достаточно для английского мира. Но как сопоставить другие текстовые символы, такие как китайский и японский? поэтому появились другие более крупные наборы символов
unicode (унифицированный набор символов), в первые дни он использовал 2 байта для представления 1 символа, а весь набор символов может содержать 65536 символов. Однако этого все еще недостаточно, поэтому он расширен до 4 байтов для представления символа, а текущий поддерживаемый диапазон составляет U+010000~U+10FFFF.
Утверждение, что unicode состоит из двух байтов, неверно;UTF-8 имеет переменную длину слова и должен храниться в 1~4 байтах; UTF-16 обычно состоит из двух байтов (диапазон U+0000~U+FFFF), если два байта не могут быть сохранены, тогда используйте 4 байта; UTF- 32 - фиксированные четыре байта
Символы, представленные Unicode, будут начинаться с «U+», за которыми следуют шестнадцатеричные числа, например, кодировка «word» — U+5B57.
Кодировка UTF-8 и набор символов Unicode
Сфера
Unicode(Binary)
Кодировка UTF-8 (двоичная)
Длина байта кодировки UTF-8
U+0000~U+007F
00000000 00000000 00000000 0XXXXXXX
0XXXXXX
1
U+0080~U+07FF
00000000 00000000 00000YYY YYXXXXXX
110YYYYY 10XXXXXX
2
U+0800~U+FFFF
00000000 00000000 ZZZZYYYY YYXXXXXX
1110ZZZZ 10YYYYYY 10XXXXXX
3
U+010000~U+10FFFF
00000000 000AAAZZ ZZZZYYYY YYXXXXXX
11110AAA 10ZZZZZZ 10YYYYYY 10XXXXXX
4
Программа разделена на внутренний код и внешний код.Кодировка java по умолчанию - UTF-8, что фактически относится к внешнему коду;Внутренний код стремится использовать код фиксированной длины, в основе которого лежит принцип выравнивания памяти, что удобно для обработки. Иностранные коды, как правило, используют коды переменной длины, которые кодируют общие символы как короткие коды, а редкие символы — как длинные коды, экономя место для хранения и полосу пропускания передачи.
Строки JDK8 используют char[] для хранения символов, char имеет размер два байта и используется кодировка UTF-16 (внутренний код).Китайские символы, указанные в Unicode, находятся в U+0000~U+FFFF, поэтому использование char (кодировка UTF-16) для хранения китайского языка не будет искажено.
После JDK9,Строки хранятся с использованием массивов byte[], потому что некоторые символы нельзя хранить в char, например символы эмодзи., использование байтов для хранения строк проще расширять
JDK9, если все содержимое строки состоит из символов ISO-8859-1/Latin-1 (1 символ 1 байт), используйте кодировку ISO-8859-1/Latin-1 для хранения строки, в противном случае используйте хранилище кодировки UTF-16. массив (2 или 4 байта)
Видно, что байты в кодировке UTF-16 — это еще два [-2][-1] байта, а шестнадцатеричное — 0xFEFF. в то время как он используется для определения порядка кодированияBig endianвсе ещеLittle endian. Возьмем, к примеру, символ '中', его шестнадцатеричный код Unicode — 4E2D. При сохранении 4E находится впереди, а 2D — сзади, что соответствует старшему порядку байтов, 2D — впереди, а 4E — сзади, что означает Little. порядок байтов FEFF означает, что хранилище использует Big endian, а FFFE означает использование Little endian.
Почему в UTF-8 нет проблем с порядком байтов?Личное мнение, т.к. UTF-8 переменная длина, то по 0, 110, 1110, 11110 заголовка первого байта определяется, нужны ли следующие байты для формирования символов, и легко читается и обрабатывается с помощью Big endian, с которым, в свою очередь, непросто справиться, поэтому он вынужден использовать Big endian
На самом деле я чувствую, что UTF-16 может принудительно использовать обратный порядок байтов, но это историческая проблема. . .
5 Краткое введение в концепцию URI
Теперь, когда есть java.io для управления потоком ресурсов, но для сетевых ресурсов, как его открыть и как найти? Ответ URI-URL
Полное имя URIUniform Resource IdentifierЕдиный идентификатор ресурса
С точки зрения непрофессионала, это строка, похожая на идентификационный номер, но она используется для идентификации ресурсов (таких как адреса электронной почты, имена хостов, файлы и т. д.).
URI имеют определенные правила:[scheme]:[scheme-specific-part][#fragment]
Дальнейшее подразделение может быть выражено как[scheme]:[//authority][/path][?query][#fragment], где конкретными частями шаблона являются полномочия, путь, запрос, а полномочия можно рассматривать как доменное имя, напримерwww.baidu.com
Завершающим подразделением является[scheme]:[//host:port][/path][?query][#fragment], это то же самое, что адресная ссылка, которую вы видите каждый день
Форма части, специфичной для схемы, зависит от схемы., а общий шаблон URI выглядит следующим образом
фтп: FTP-сервер
файл: файл на локальном диске
http: использовать протокол передачи гипертекста
mailto: адрес электронной почты
telnet: подключение к службам на основе Telnet
В Java также широко используются некоторые нестандартные режимы настройки, такие как rmi, jar, jndi, doc, jdbc и т. д.
В java URI абстрагируется как класс java.net.URI Ниже перечислены несколько распространенных методов построения.
//根据str生成URI
public URI(String str) throws URISyntaxException
public URI(String scheme, String authority,
String path, String query, String fragment)throws URISyntaxException
public static URI create(String str) //调用 URI(String str)
Общие методы работы JAVA.URI
public String getScheme() //获取模式
public String getSchemeSpecificPart()//获取模式特定部分
public String getFragment() //获取片段标识符
//以上三个方法是通用的
public String getAuthority() //授权机构,如www.baidu.com
public String getHost() //获取主机部分,如127.0.0.1
public int getPort() //如8080
public String getPath() //定位路径
public String getQuery() //查询条件
6 Понятие URL и отличие от URL
Полное имя URL-адресаUniform Resource Location, Унифицированный указатель ресурсов
URL — это подмножество URI, которое помимо идентификации ресурсов также предоставляет путь для поиска ресурсов;В библиотеке классов Java класс URI не содержит никаких методов для доступа к ресурсам, его единственная функция — разрешение, а класс URL может открывать поток для доступа к ресурсу.
URN (унифицированные имена ресурсов), которые принадлежат одному и тому же подмножеству URI,Идентифицирует только имя ресурса, не указывая, как найти ресурс;как:mailto:clswcl@gmail.comЭто своего рода URN Я знаю, что это почтовый ящик, но я не знаю, как его найти и найти.
Проще говоря, URN говорит вам, что есть место под названием Гуанчжоу, но не говорит, как туда добраться. Вы можете сесть на поезд или самолет; URL-адрес скажет вам отправиться в Гуанчжоу на самолете, а другой URL-адрес говорит ехать поездом
Функция операции для получения данных ресурса через URL
public final InputStream openStream() throws java.io.IOException
public URLConnection openConnection() throws java.io.IOException
public final Object getContent() throws java.io.IOException
7 методов получения ресурсов Spring.Resource и Spring
Когда дело доходит до ресурсов, мы должны упомянуть, как Spring получает ресурсы.Существуют два наиболее часто используемых метода.
Получить ресурсы через подклассы интерфейса Resource
Получить ресурсы через подклассы интерфейса ResourceLoader
Функции манипулирования списком ресурсов Spring.Resource
Познакомить с использованием подклассов, связанных с ресурсами.
1 FileSystemResource: Получить ресурсы через файловую систему
Resource resource = new FileSystemResource("D:/example.txt");
File file= new File("example.txt");
Resource resource2 = new FileSystemResource(file);
2 ByteArrayResource: получить ресурс, представленный массивом байтов.
Основанный на реализации ByteArrayInputStream и массива байтов, сценарий приложения аналогичен ByteArrayInputStream, кэшируя ресурсы byte[]
3 ClassPathResource: получить ресурсы по пути к классам
//ClassPathResource.java 的三个属性
private final String path;
//使用Class或ClassLoader加载资源
private ClassLoader classLoader;
private Class<?> clazz;
---使用方式----
Resource resource = new ClassPathResource("test.txt");
4 InputStreamResource: получить объект InputStream и получить ресурсы, инкапсулированные входным потоком.
5 ServletContextResourse: загрузить ресурсы пути в среду ServletContext (относительно корневого каталога веб-приложения) и получить ресурсы
6 UrlResource: доступ к ресурсам http и FTP через URL-адреса и т. д.
8 ResourceLoader для получения ресурсов
resource.png
ResourceLoader предназначен для защиты конкретной реализации Resource и унификации способа получения ресурсов. Вы можете загрузить ClassPathResource из ResourceLoader, FileSystemResource и т. д.
ResourcePatternResolver загрузит все файлы по указанному пути по умолчанию, чтобы получить ClassPathResource;classpath: будет искать только путь к классам и classpath*: будет сканировать все пакеты JAR и файлы, которые появляются в пути к классам.
LocationPattern метода getResource ResourceLoader может установить префикс шаблона ресурса для получения ресурсов, отличных от ClassPathResource.locationPattern поддерживает стиль Ant.
префикс
Пример
описывать
classpath:
classpath:config.xml
Загрузить из пути к классам
file:
file:///res.txt
Загрузить FileSystemResource из файловой системы
http:
http://my.cn/res.txt
Загрузить URL-ресурс
9 JAVA.Properties, которые нужно понять
Properties — это класс обработки конфигурации, который поставляется с java; два способа загрузки ресурсов свойствами
public class Properties extends Hashtable<Object,Object>{
.... //可根据Reader或者InputStream加载properties文件内容
public synchronized void load(Reader reader) throws IOException
public synchronized void load(InputStream inStream) throws IOException
Обычные java-проекты могут импортировать jackson-dataformat-yaml, если им нужно читать yml, а конфигурация springboot по умолчанию поддерживает чтение yml
11 Аккуратное закрытие ресурсов, синтаксис try-with-resource и lombok@Cleanup
Открытие ресурсов требует соответствующего закрытия, но мы часто забываем закрыть ресурсы или чувствуем себя загроможденными, закрывая ресурсы в нескольких кодах.Есть ли краткий метод закрытия?
Для автоматического закрытия классов ресурсов необходимо реализовать интерфейс AutoCloseable и использовать с сахаром синтаксиса try-with-resource.
public class YSOAPConnection implements AutoCloseable {
private SOAPConnection connection;
public static YSOAPConnection open(SOAPConnectionFactory soapConnectionFactory) throws SOAPException {
YSOAPConnection ySoapConnection = new YSOAPConnection();
SOAPConnection connection = soapConnectionFactory.createConnection();
ySoapConnection.setConnection(connection);
return ySoapConnection;
}
public SOAPMessage call(SOAPMessage request, Object to) throws SOAPException {
return connection.call(request, to);
}
@Override
public void close() throws SOAPException {
if (connection != null) { connection.close(); }
}
}
аннотация lombok @Cleanup будет вызываться, когда закончится жизненный цикл объектаpublic void close();Объект должен реализовать интерфейс AutoCloseable
После JDK9 механизм finalize заменяется механизмом Cleaner; объекты, автоматически возвращаемые механизмом Cleaner, также должны реализовывать интерфейс AutoCloseable; Cleaner реализуется на основе PhantomReference; учащиеся, интересующиеся деталями реализации, могут обратиться к соответствующим документы.
Однако если используется механизм закрытия ресурсов, предоставляемый JDK, закрытие ресурсов будет отложено на долгое время по сравнению с закрытием вручную. Согласно тесту,Используйте try-with-resources, чтобы закрыть ресурс и позволить сборщику мусора собрать его за 12 наносекунд. При использовании механизма финализатора время увеличивается до 550 наносекунд.
Если ресурс не будет закрыт вовремя, он займет ресурс и повлияет на выполнение других потоков; например, файловый ресурс linux, максимальное количество файлов, которые может открыть процесс linux по умолчанию, составляет 1024 (некоторые 2048). , это значение настраивается); если поток содержит более дюжины файловых ресурсов, необходимо подождать 550 наносекунд, чтобы использовать механизм финализатора для освобождения ресурсов, а другие потоки в том же процессе будут ждать, пока цветы не исчезнут.
Добро пожаловать на ошибку в тексте
Обратите внимание на публичный номер и общайтесь вместе