Java#33(IO流)

news2024/11/17 19:46:11

目录

一.IO流

作用: (对于程序而言)用于读写数据(本地数据, 网络数据)

二.IO流体系 

 1.字节输出流

2.字节输入流

 3.文件拷贝

 3.字符集

字符流

字符输入流

字符输出流

缓冲流

转换流 

序列化流 

​编辑反序列流

打印流


一.IO流

I: input     O: output     流: 想流水一样传输数据

作用: (对于程序而言)用于读写数据(本地数据, 网络数据)

(写)输出流(output):  程序-------->文件

(读)输入流(input):  文件--------->程序

IO流按照操作文件的类型可以分类为:

字节流: 可以操作所有类型的文件

字符流: 只能操作纯文本文件(用window系统自带的记事本打开并且能够读懂的文件)

二.IO流体系 

 1.字节输出流

FileOutputStream

代码示范:

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class IODemo1 {
    public static void main(String[] args) throws IOException {
        FileOutputStream fos = new FileOutputStream("C:\\Users\\怪\\Desktop\\abc\\b.txt");
        fos.write(97);
        fos.close();
    }
}

结果展示:

注意:

(1)创建字节输出流对象, 参数可以是字符串代表的路径或File对象

(2)创建字节输出流对象, 如果文件不存在会创建一个新的文件,不过要保证父级路径存在

(3)创建字节输出流对象, 如果文件已经存在,会先清空文件

(4)在写数据时, write方法的参数时整数, 但实际上存进去的是ASCII码值对应的字符

(5)释放资源, 每次使用完流后都要释放资源

FileOutputStream写数据的3种方式
        方法名称                                                          说明
void write(int b)                                        一次写一个字节数据
void write(byte[ ] b)                                一次写一个字节数组数据
void write(byte[ ] b,int off,int len)    一次写一个字节数组的部分数据
代码示范: 

import java.io.FileOutputStream;
import java.io.IOException;

public class IODemo2 {
    public static void main(String[] args) throws IOException {
        FileOutputStream fos = new FileOutputStream("D:\\Java\\java\\Demo2_12_4\\src\\a.txt");
        //1.write(int b)
        //fos.write(97);
        //2.write(byte[])
        byte[] bt1 = {97,98,99,100,101,102};
        //fos.write(bt1);
        //3.write(byte[],int off,int len)
        //int off起始索引  int len 个数
        fos.write(bt1,0,3);
        fos.close();
    }
}

运行write(byte[ ] b)结果展示:运行write(byte[ ] b, int off, int len)结果展示: 

如何换行写?

代码示范: 

import java.io.FileOutputStream;
import java.io.IOException;

public class IODemo3 {
    public static void main(String[] args) throws IOException {
        FileOutputStream fos = new FileOutputStream("D:\\Java\\java\\Demo2_12_4\\src\\a.txt");
        //将字符串转化为字节类型
        String s1 = "abc";
        byte[] bytes1 = s1.getBytes();
        fos.write(bytes1);
        //换行操作
        String s2 = "\r\n";
        byte[] bytes2 = s2.getBytes();
        fos.write(bytes2);
        //在添加字符
        String s3 = "123";
        byte[] bytes3 = s3.getBytes();
        fos.write(bytes3);
        fos.close();
    }
}

结果展示:

如何实现续写? 

在创建FileOutputStream对象的第二个参数写上true(表示打开续写, 默认为false)

2.字节输入流

FileInputStream: 操作本地文件的字节输入流, 可以把本地文件的数据读取到程序中来

代码示范: 

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

public class IOStreamDemo1 {
    public static void main(String[] args) throws IOException {
        FileInputStream fis = new FileInputStream("D:\\Java\\java\\Demo1_12_5\\src\\IOStreamDemo\\b.txt");
        int read1 = fis.read();//返回的是对应的ASCII码值
        System.out.println(read1);
        int read2 = fis.read();
        System.out.println((char)read2);
        int read3 = fis.read();
        System.out.println((char)read3);
        int read4 = fis.read();
        System.out.println(read4);
        fis.close();
    }
}

结果展示:

 注意: 读到末尾就是-1

FileInputStream的循环读取

代码示范: 

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

public class IOStreamDemo2 {
    public static void main(String[] args) throws IOException {
        FileInputStream fis = new FileInputStream("D:\\Java\\java\\Demo1_12_5\\src\\IOStreamDemo\\b.txt");
        //创建一个变量来存储
        int a = 0;
        //read: 读取数据,并将下标移动的下一位
        //利用末尾是-1来作为结束标志
        while((a = fis.read())!=-1){
            System.out.println((char)a);
        }
        fis.close();
    }
}

结果展示: 

 3.文件拷贝

核心思想: 边读边写

代码示范: 

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class IOStreamDemo3 {
    public static void main(String[] args) throws IOException {
        FileInputStream fis = new FileInputStream("C:\\Users\\怪\\Desktop\\abc\\aa.txt");
        FileOutputStream fos = new FileOutputStream("D:\\Java\\java\\Demo1_12_5\\src\\IOStreamDemo\\b.txt");
        int a = 0;
        while((a = fis.read()) != -1){
            fos.write(a);
        }
        //释放资源
        //先创建的后释放
        fos.close();
        fis.close();
    }

结果展示:

FileInputStream一次读取多个字节

代码示范: 

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

public class IOStreamDemo4 {
    public static void main(String[] args) throws IOException {
        FileInputStream fis = new FileInputStream("D:\\Java\\java\\Demo1_12_5\\src\\IOStreamDemo\\b.txt");
        //一次读取多个字节数据,有数组长度决定
        byte[] by1 = new byte[2];
        //本次读取了多少个字节
        int len1 = fis.read(by1);
        System.out.println(len1);
        String str1 = new String(by1,0,len1);
        System.out.println(str1);

        int len2 = fis.read(by1);
        System.out.println(len2);
        String str2 = new String(by1,0,len2);
        System.out.println(str2);

        int len3 = fis.read(by1);
        System.out.println(len1);
        String str3 = new String(by1,0,len3);
        System.out.println(str3);
        fis.close();

    }
}

结果展示: 

 3.字符集

GBK字符集

1.在计算机中,任意数据都是以二进制的形式来存储的

2.计算机中最小的存储单元是一个字节
3.ASCII字符集中,一个英文占一个字节
4.简体中文版Windows,默认使用GBK字符集
5.GBK字符集完全兼容ASCII字符集
一个英文占一个字节,二进制第一位是0
一个中文占两个字节,二进制高位字节的第一位是1

Unicode字符集

1.Unicode字符集的UTF-8编码格式(UTF-8是Unicode中的一种编码方式,不是字符集)
一个英文占一个字节,二进制第一位是0,转成十进制是正数

一个中文占三个字节,二进制第一位是1,第一个字节转成十进制是负数

产生乱码的原因:
1. 不要用字节流读取文本文件
2. 编码解码时使用同一个码表,同一个编码方式

编码和解码方法

编码
        String类中的方法                                                              说明
public byte[ ] getBytes()                                           使用默认方式进行编码
public byte[ ] getBytes(string charsetName)         使用指定方式进行编码
解码
        String类中的方法                                                              说明
string(byte[] bytes)                                                    使用默认方式进行解码
string(bytel] bytes,string charsetName)               使用指定方式进行解码
代码示范: 

import java.io.UnsupportedEncodingException;
import java.util.Arrays;

public class Demo1 {
    public static void main(String[] args) throws UnsupportedEncodingException {
        String str1 = "ni们好";
        //默认UTF-8
        byte[] bytes1 = str1.getBytes();
        System.out.println(Arrays.toString(bytes1));
        //GBK
        byte[] bytes2 = str1.getBytes("GBK");
        System.out.println(Arrays.toString(bytes2));

        //解码
        //默认
        String str2 = new String(bytes1);
        System.out.println(str2);
        //GBK
        String str3 = new String(bytes1,"GBK");
        System.out.println(str3);//为什么会乱码?
                        //因为bytes1是用UTF-8进行编码的
                        //而str3是用GBK进行解码的,所以会乱码
    }
}

结果展示: 

字符流

字符流的底层其实就是字节流
字符流 = 字节流 + 字符集
特点:
输入流:一次读一个字节,遇到中文时,一次读多个字节

输出流:底层会把数据按照指定的编码方式进行编码,变成字节再写到文件中
注意:
只能对纯文本文件进行读写操作

字符输入流

步骤:

第一步:创建对象
public FileReader(File file)            创建字符输入流关联本地文件

public FileReader(String pathname)创建字符输入流关联本地文件
第二步: 读取数据

public int read()            读取数据,读到末尾返回-1
public int read(char[] buffer)        读取多个数据,读到末尾返回-1
第三步:释放资源
public void close()            释放资源/关流

代码示范:无参read( )

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

public class FileReaderDemo1 {
    public static void main(String[] args) throws IOException {
        FileReader fr = new FileReader("D:\\Java\\java\\Demo1_12_6\\src\\c.txt");
        //读取数据
        int ch;
        while ((ch = fr.read()) != -1) {
            System.out.print((char)ch);
        }
        //释放资源
        fr.close();
    }
}

结果展示:

注意:ch表示的不是二进制的数值,而是对应十进制的数值

 代码示范: 有参read(char[ ] 变量名)

import java.io.FileReader;
import java.io.IOException;

public class FileReaderDemo2 {
    public static void main(String[] args) throws IOException {
        FileReader fr = new FileReader("D:\\Java\\java\\Demo1_12_6\\src\\c.txt");
        //一次读取多个数据
        char[] ch1 = new char[3];
        int len;
        //有参read方法
        while ((len = fr.read(ch1)) != -1) {
            System.out.print(new String(ch1,0,len));
        }
        //释放资源
        fr.close();
    }
}

结果展示: 

字符输出流

步骤:

第一步:创建对象
public FileWriter(File file)                                               创建字符输出流关联本地文件
public Filewriter(String pathname)                                创建字符输出流关联本地文件
public FileWriter(File file, boolean append)              创建字符输出流关联本地文件, 可续写
public Filewriter(string pathname, boolean append)   创建字符输出流关联本地文件,可续写 
第二步:读取数据
void write(int c)                                                写出一个字符
void write(string str)                                      写出一个字符串
void write(String str, int off, int len)        写出一个字符串的一部分
void write(char[] cbuf)                                 写出一个字符数组   
void write(char[] cbuf, int off, int len)      写出字符数组的一部分
第三步:释放资源
public void close()                                           释放资源/关流

代码示范:

import java.io.FileWriter;
import java.io.IOException;

public class FileWriteDemo1 {
    public static void main(String[] args) throws IOException {
                                                                                    //true表示打开续写
        FileWriter fw = new FileWriter("D:\\Java\\java\\Demo1_12_6\\src\\c.txt",true);
        //写入数据
        fw.write("字节");
        char[] ch1 = {'1','a','c'};
        fw.write(ch1);
        //释放资源
        fw.close();
    }
}

结果展示: 

缓冲流

缓冲流可以提高性能,如何提高性能?

缓冲流自带8192的缓冲区

可以提高字节流的读写性能

对字符流就没有那么明显, 但有两个特有方法

字符输出流特有的方法: BufferedReader: readLine( )(读取一行代码, 没有数据可以读取就返回null)

字符输出流特有的方法: BufferedWriter: newLine( )(跨平台换行)

字节缓冲流拷贝文件

代码示范:

import java.io.*;

public class BufferedStreamDemo1 {
    public static void main(String[] args) throws IOException {
        //利用字节缓冲流拷贝文件
        //创建对象
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("D:\\Java\\java\\Demo1_12_7\\src\\BufferedInputStreamDemo1\\a.txt"));
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("D:\\Java\\java\\Demo1_12_7\\src\\BufferedInputStreamDemo1\\copy.txt"));
        //循环读取
        int b = 0;
        while((b = bis.read()) != -1){
            bos.write(b);
        }
        //释放资源
        bos.close();
        bis.close();

    }
}

结果展示: 

字符缓冲流特有方法

readLine( )代码示范:

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class Test1 {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new FileReader("D:\\Java\\java\\Demo1_12_7\\src\\BufferedInputStreamDemo1\\a.txt"));

        String str = br.readLine();
        System.out.println(str);
        br.close();
    }
}

结果展示:

newLine( )代码示范:

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;

public class Test2 {
    public static void main(String[] args) throws IOException {
        BufferedWriter bw = new BufferedWriter(new FileWriter("D:\\Java\\java\\Demo1_12_7\\src\\BufferedInputStreamDemo1\\copy1.txt"));
        String s1 = "繁星";
        bw.write(s1);
        bw.newLine();
        String s2 = "春水";
        bw.write(s2);
        bw.newLine();
        bw.close();
    }
}

结果展示: 

转换流 

InputStreamReader

OutStreamWriter

作用: 让字节流可以使用字符流中的方法

代码示范: 让字节流使用字符缓冲流

import java.io.*;

public class Test2 {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("D:\\Java\\java\\Demo2_12_7\\src\\InputStreamReaderDemo1\\aa.txt")));
        String str = br.readLine();
        System.out.println(str);
        br.close();
    }
}

结果展示:

序列化流 

可以把Java中的对象写到本地文件中

构造方法
public Objectoutputstream(Outputstream out)  把基本流包装成高级流
成员方法
public final void writeobject(object obi)        把对象序列化(写出)到文件中去
代码示范:第一段是类的代码,第二段是测试代码

import java.io.Serializable;

public class Student implements Serializable {
    private String name;
    private int age;

    public Student() {
    }

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    /**
     * 获取
     * @return name
     */
    public String getName() {
        return name;
    }

    /**
     * 设置
     * @param name
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * 获取
     * @return age
     */
    public int getAge() {
        return age;
    }

    /**
     * 设置
     * @param age
     */
    public void setAge(int age) {
        this.age = age;
    }

    public String toString() {
        return "Student{name = " + name + ", age = " + age + "}";
    }
}
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;

public class Test3 {
    public static void main(String[] args) throws IOException {
        Student stu = new Student("张三",65);
        //创建对象
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("D:\\Java\\java\\Demo2_12_7\\src\\InputStreamReaderDemo1\\a.txt"));
        //使用成员方法
        oos.writeObject(stu);
        //释放资源
        oos.close();
    }
}

结果展示:

 注意:

类要实现Serializable接口,不然就会报错(Serializable接口里面是没有抽象方法,是标记型接口
一旦实现了这个接口,那么就表示当前的类可以被序列化)


反序列流

构造方法
public objectInputstream(Inputstream out)    把基本流变成高级流
成员方法
public object readObject()                 把序列化到本地文件中的对象,读取到程序中来

代码示范:

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.ObjectInputStream;

public class Test4 {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        //创建对象
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("D:\\Java\\java\\Demo2_12_7\\src\\InputStreamReaderDemo1\\a.txt"));
        //使用方法
        Object o1 = ois.readObject();
        System.out.println(o1);
        //释放资源
        ois.close();
    }
}

结果展示:

打印流

作用:打印流可以实现方便、高效的打印数据到文件中去

打印流一般是指: PrintStream,PrintWriter
可以实现打印什么数据就是什么数据,例如打印整数97写出去就是97,打印boolean的true,写出去就是true。
PrintStream
                构造方法                                                          说明
public PrintStream(Outputstream os)         打印流直接通向字节输出流管道
public PrintStream(File f)                                 打印流直接通向文件对象
public PrintStream(String filepath)                 打印流直接通向文件路径
                 方法
public void print(Xxx xx)                           打印任意类型的数据出去 

代码示范:PrintStream( )

import java.io.FileNotFoundException;
import java.io.PrintStream;
import java.io.PrintWriter;

public class PrintStreamDemo1 {
    public static void main(String[] args) throws FileNotFoundException {
        //创建对象
        PrintStream ps = new PrintStream("D:\\Java\\java\\Demo3_12_7\\src\\a.txt");
        //添加数据
        ps.println(123);
        ps.println("abc");
        ps.println(123.456);
        ps.println(true);
        //释放资源
        ps.close();
    }
}

结果展示: 

 PrintWriter( )和PrintStream的打印基本一致

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/72891.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux下创建动态链接库与静态链接库

动态链接库 Linux下的动态链接库文件扩展名为so,可以用多个文件生成一个动态链接库。 在头文件中定义三个函数,三个函数分别于三个cpp文件中实现。 将三个cpp文件编译成动态库libdynamic.so -fPIC表示编译为位置独立的代码,如果不选择默…

使用YOLOv5练自己的数据集

说明 上次使用学习了如何运行yolov5检测自己的数据,这次学习yolov5如何训练自己的数据集 本次记录如何使用yolov5训练自己的数据集以及遇到报错解决方案 数据 使用数据:水果数据集 数据包含了png图片和相应的标注文件 切分数据 代码如下&#xff1…

[ vulhub漏洞复现篇 ] solr 远程命令执行(CVE-2019-0193)

🍬 博主介绍 👨‍🎓 博主介绍:大家好,我是 _PowerShell ,很高兴认识大家~ ✨主攻领域:【渗透领域】【数据通信】 【通讯安全】 【web安全】【面试分析】 🎉点赞➕评论➕收藏 养成习…

Kubernetes的基础概念

一、Kubernetes的介绍 用于自动部署、扩展和管理"容器化(containerized)应用程序"的开源系统 可以理解成K8S是负责自动化运维管理多个容器化程序(比如Docker)的集群,是一个生态极其丰富的容器编排框架工具 …

【现场问题】zookeeper的集群,其中两台起来了,但是另外一台就是起不来,或者起来也是standalone

zookeeper问题现象集群的配置zookeeper的启动以及状态查看问题报错点问题现象 1、总共三台机器,node92,node93,node94 其中node92做了拉起,但是node93(leader)和node94(follower)&a…

浅谈MVVM ——Model-View-View-Model

浅谈MVVM ——Model-View-View-Model 前言: 笔者最近接到这样一个机器人项目,接入他们的机器人平台做二次开发,开发自己的opk移植到机器人上做医院展示使用。opk是必须使用机器人厂家提供的经过一定封装过的,该opk的架构是MVVM。…

48W字?GitHub上下载量破百万的阿里:图解Java、网络、算法笔记

Java基础这个东西,无论在哪个公司都被看得尤为重要,而面试中关于基础的问题也是层出不穷。所以基础可以说是重中之重,当你的基础打牢了,其他的也就没有那么重要了。 说到基础,无外乎操作系统,网络&#xf…

pikachu-CSRF-SSRF-RCE速通

pikachu-CSRF-SSRF-RCE速通 目录pikachu-CSRF-SSRF-RCE速通CSRFCSRF(get)CSRF(post)CSRF TokenSSRFSSRF(curl)SSRF(file_get_content)RCEexec "ping"RCE exec "eval"CSRF 跨站请求伪造,说的通俗一点就是攻击者构造出某个网站的数据包请求并部署…

p3.第一章 基础入门 -- Python编程基本概念 (三)

1.2.2 Python语言 1.2.2.1 Python发展 1989年圣诞节期间,为了打发无聊的时间,荷兰人Guido van Rossum(吉多范罗苏姆)(数学、计算机双硕士,2005年加入Google,2013年加入DropBox)&am…

JavaUUID的理解

可笑,你竟然不知道 Java 如何生成 UUID - 沉默王二博客 UUID是通用唯一标识符的意思,就是唯一不重复的一串字符。 UUID的用途: 随机生成的文件名;Java Web 应用程序的 sessionID;数据库表的主键;事务 ID&…

EMQ 助力阿里云洛神云网络构建新一代“亿级并发、百万级吞吐”NLB 网络型负载均衡系统

万物智联的数字化时代,我们正走在从“数据量变”到“连接质变”的道路上。在日益丰富的物联网应用场景中,实现海量设备与云端之间双向通信连接,分析并从中获得实时洞察成了打造成功物联网解决方案的核心推动因素。EMQ 映云科技(以下简称“EMQ”)作为全球领先的开源物联网基础设…

UE在TextRender上显示中文文本

文章目录 1.实现目标2.实现过程2.1 添加字体2.2 创建字体材质2.3 将字体应用到TextRender3.参考资料1.实现目标 UE的UMG可以正常支持中文,但是TextRender并不支持中文,因此需要添加本地离线中文字体库,使TextRender显示中文。 2.实现过程 2.1 添加字体 (1)选择User Int…

day6bom操作浏览器

apis-day6bom-操作浏览器 文章目录apis-day6bom-操作浏览器1、window对象1.1BOM(浏览器对象模型1.2定时器-延时函数1.3JS执行机制(重要)1.4 location对象1.5 navigator对象1.6histroy对象(用的少)2、swiper插件3、本地存储&#x…

当前的数字化,CIO 们到底需要什么?

“做数字化,没人、没钱、没资源,但还要做效果,该怎么办?” 这是很多 CIO 当下都面临的困境。 那么,对于不同企业来说,到底该如何有效探索数字化转型之路呢? 数字化转型的三个阶段 Gartner 把…

简易黑客初级教程:黑客技术,分享教学

前言 第一节,伸展运动。这节操我们要准备道具,俗话说:“工欲善其事,必先利其器”(是这样吗?哎!文化低……)说得有道理,我们要学习黑客技术,一点必要的工具必不可少。 1,一台属于自己的可以上…

【面试题】2023 中级前端面试题

前言 从前端学习到找一份合适的工作,大大小小的面试必不可少,所以我对初级前端面试题进行了初步整理,也方便自己查阅,也希望对小伙伴们有所帮助! 给大家推荐一个实用面试题库 1、前端面试题库 (面试必备&…

C语言——内存中数据存储的详解(整型与浮点型)

文章目录1.数据类型的详细介绍1.1数据类型介绍1.2类型的基本归类整型类型浮点类型构造类型指针类型空类型2.整型在内存中的存储2.1原码、反码、补码2.2大小端存储大小端存储存在的意义编写一个程序判断当前机器的存储方式是大端存储还是小端存储2.3经典习题练习一练习二练习三c…

Prometheus部署Prometheus Server、Pushgateway、Node exporter、AlertManager

目录1. 安装Prometheus Server1.1 下载解压1.2 修改配置文件prometheus.yml1.3 启动Prometheus Server2. 安装Pushgateway2.1 下载解压2.2 启动Pushgateway3. 安装Node Exporter3.1 下载解压3.2 启动Node Exporter4. 安装Alertmanager4.1 下载解压4.2 启动Alertmanager1. 安装P…

CS5518 MIPI转LVDS转换方案芯片|DSI转LVDS转换方案芯片

CS5518 是一款MIPI DSI 至 LVDS 转换器方案芯片。 Capstone CS5518是一款MIPI DSI输入、LVDS输出转换芯片。MIPI DSI 支持多达4个局域网,每条通道以最大 1Gbps 的速度运行。LVDS支持18位或24位像素,25Mhz至154Mhz,采用VESA或JEIDA格式。它只…

CMake中target_sources的使用

CMake中的target_sources命令用于将源添加到target&#xff0c;其格式如下&#xff1a; target_sources(<target><INTERFACE|PUBLIC|PRIVATE> [items1...][<INTERFACE|PUBLIC|PRIVATE> [items2...] ...]) # general formtarget_sources(<target>[<…