精华内容
下载资源
问答
  • 先说结论:上面的调用表明将./test.sh的输出重定向log.txt文件中,同时将标准错误也重定向log.txt文件中。 有何妙用 (如果已经明白是什么作用,可跳过此小节) 上面到底是什么意思呢?我们来看下面的例子,假如...

    前言

    有时候我们常看到类似这样的脚本调用:

    ./test.sh > log.txt 2>&1
    这里的2>&1是什么意思?该如何理解?
    先说结论:上面的调用表明将./test.sh的输出重定向到log.txt文件中,同时将标准错误也重定向到log.txt文件中。

    有何妙用

    (如果已经明白是什么作用,可跳过此小节)
    上面到底是什么意思呢?我们来看下面的例子,假如有脚本test.sh:

    #!/bin/bash
    date         #打印当前时间
    while true   #死循环
    do
        #每隔2秒打印一次
        sleep 2
        whatthis    #不存在的命令
        echo -e "std output"
    done
    

    脚本中先打印当前日期,然后每隔2秒执行whatthis并打印一段字符。由于系统中不存在whatthis命令,因此执行会报错。
    假如我们想保存该脚本的打印结果,只需将test.sh的结果重定向到log.txt中即可:

    ./test.sh > log.txt
    执行结果如下:

    ubuntu$ ./test.sh >log.txt
    ./test.sh: 行 7: whatthis: 未找到命令
    

    我们明明将打印内容重定向到log.txt中了,但是这条错误信息却没有重定向到log.txt中。如果你是使用程序调用该脚本,当查看脚本日志的时候,将会完全看不到这条错误信息。而使用下面的方式则会将出错信息也重定向到log.txt中:

    ./test.sh > log.txt 2>&1
    以这样的方式调用脚本,可以很好的将错误信息保存,帮助我们定位问题。

    如何理解

    每个程序在运行后,都会至少打开三个文件描述符,分别是0:标准输入;1:标准输出;2:标准错误。
    例如,对于前面的test.sh脚本,我们通过下面的步骤看到它至少打开了三个文件描述符:

    ./test.sh    #运行脚本
    ps -ef|grep test.sh  #重新打开命令串口,使用ps命令找到test.sh的pid
    hyb       5270  4514  0 19:20 pts/7    00:00:00 /bin/bash ./test.sh
    hyb       5315  5282  0 19:20 pts/11   00:00:00 grep --color=auto test.sh
    

    可以看到test.sh的pid为5270,进入到相关fd目录:

    cd /proc/5270/fd   #进程5270所有打开的文件描述符信息都在此
    ls -l              #列出目录下的内容
     0 -> /dev/pts/7
     1 -> /dev/pts/7
     2 -> /dev/pts/7
     255 -> /home/hyb/workspaces/shell/test.sh
    

    可以看到,test.sh打开了0,1,2三个文件描述符。同样的,如果有兴趣,也可以查看其他运行进程的文件描述符打开情况,除非关闭了否则都会有这三个文件描述符。

    那么现在就容易理解前面的疑问了,2>&1表明将文件描述2(标准错误输出)的内容重定向到文件描述符1(标准输出),为什么1前面需要&?当没有&时,1会被认为是一个普通的文件,有&表示重定向的目标不是一个文件,而是一个文件描述符。在前面我们知道,test.sh >log.txt又将文件描述符1的内容重定向到了文件log.txt,那么最终标准错误也会重定向到log.txt。我们同样通过前面的方法,可以看到test.sh进程的文件描述符情况如下:

     0 -> /dev/pts/7
     1 -> /home/hyb/workspaces/shell/log.txt
     2 -> /home/hyb/workspaces/shell/log.txt
     255 -> /home/hyb/workspaces/shell/test.sh
    

    我们可以很明显地看到,文件描述符1和2都指向了log.txt文件,也就得到了我们最终想要的效果:将标准错误输出重定向到文件中。
    它们还有两种等价写法:

    ./test.sh  >& log.txt
    ./test.sh  &> log.txt
    

    总结

    我们总结一下前面的内容:

    程序运行后会打开三个文件描述符,分别是标准输入,标准输出和标准错误输出。
    在调用脚本时,可使用2>&1来将标准错误输出重定向。
    只需要查看脚本的错误时,可将标准输出重定向到文件,而标准错误会打印在控制台,便于查看。

    >>log.txt会将重定向内容追加到log.txt文件末尾。
    通过查看/proc/进程id/fd下的内容,可了解进程打开的文件描述符信息。
    

    思考

    下面的调用会将标准错误输出重定向到文件中吗?为什么?

    ./test.sh 2>&1 >log.txt 
    
    展开全文
  • 2是什么意思? >:箭头代表重定向du &:代表引用 2:代表标准错误输出zhi 同类的是 0 表示daostdin标准输入 1 表示stdout标准输出 2 表示stderr标准错误 那你这个>&2的含义:把前面的打印消息...

    1、Shell 中的两个特殊文件“/dev/null”和“/dev/tty”

    1. /dev/null
      当被用作重定向输出时,程序的输出被直接丢弃。该文件用在哪些不关心程序输出的地方。
      当被用作重定向输入时,输入则是文件结束。

    2. /dev/tty
      当被用作重定向时,表示重定向到终端。

    基本命令查找

    shell 会沿着$PATH 来寻找命令。$PATH 是一个以冒号分割的目录列表,你可以在列表所指定的目录下找到所要执行的命令。命令可能是 shell 脚本,也可能是编译后的可执行文件,从用户角度来看,二者并无不同。
    默认路径至少包含/bin 和/usr/bin,或许还包含其他的。
    名称为 bin 的目录用来保存可执行文件。

    如果要编写自己的脚本,最好准备一个自己的 bin 目录来存放他们,并且让 shell 能够自动找到他们。

    $cd  
    $mkdir bin   
    $mv nusers bin  
    $PATH+$PATH:$HOME/bin         //将个人的 bin 目录附加到 PATH(暂时生效,系统重启后失效)  
    nusers

    要想永久生效,在/etc/profile 文件中把你的 bin 目录加入到$PATH,而每次登陆时 Shell 都将读取.profile 文件。
    PATH=$PATH:$HOME/bin
    $PATH 里的空项目表示当前项目。空项目位于路径中间时,可以用两个连续的冒号来表示,如果将冒号直接置于最前端或尾端,分别表示查找的时候最先查找或最后查找当前目录。

    $PATH=:/bin:/usr/bin            先找当前目录  
    $PATH=/bin::/usr/bin            当前目录居中  
    $PATH=/bin:/usr/bin:            最后找当前目录  

    <,>,>>以及| 是基本的 I/O 重定向符

    重定向的使用规律

    • 标准输入0、输出1、错误2需要分别重定向,一个重定向只能改变它们中的一个
    • 标准输入0和标准输出1可以省略。(当其出现重定向符号左侧时)
    • 文件描述符在重定向符号左侧时直接写即可,在右侧时前面加&
    • 文件描述符与重定向符号之间不能有空格

    2、在shell里面>&2是什么意思?

    > 箭头代表重定向
    & 代表引用
    2 表示STDERR标准错误输出
    0 表示STDIN标准输入
    1 表示STDOUT标准输出

    那你这个 >&2 的含义:把前面的打印消息重定向到标准错误里面。(错误信息才输出)

    Shell会自动为我们打开和关闭0、1、2这三个文件描述符,我们不需要显式地打开或关闭它们。标准输入是命令的输入,默认指向键盘;标准输出是命令的输出,默认指向屏幕;标准错误是命令错误信息的输出,默认指向屏幕。

    "某个命令" 1>/dev/null 2>&1

    执行这个命令,然后这个命令执行过程中的所有标准输出都重定向到/dev/null,空设备的意思就是标准输出不打印,

    2>&1 就是标准错误重定向到标准输出中。而标准输出前面已经说了不打印。那么整体就是标准输出,标准错误都不打印。

    如果没有前提“而标准输出前面已经说了不打印”,2>&1  意思就很明了了,就是讲执行linux命令时的错误信息也输出到屏幕上。

    >&2 使用的比较少,我们很少把其他信息重定向到标准错误中。

    https://wiki.jikexueyuan.com/project/shell-learning/sectionalization.html

    3、实践

    这里使用(echo 1; echo1 1)命令测试

    $ (echo 1; echo1 1)
    1
    bash: echo1: command not found
    
    # 可以看到标准输出进了1.log,标准输入0和标准输出1可以省略。(当其出现重定向符号左侧时)
    $ (echo 1; echo1 1)>1.log
    bash: echo1: command not found
    $ cat 1.log
    1
    
    # 可以看到标准输出进入了1.log,标准错误进入了2.log
    $ (echo 1; echo1 1) 1>1.log 2>2.log
    $ cat 1.log
    1
    $ cat 2.log
    bash: echo1: command not found
    
    # 表示把错误出定向到标准输出(此时标准输出为终端,所以输出到终端), 标准输出定位到文件( >1.log其实是1>1.log),所以看到错误信息输出到终端,而正确信息保存到了1.log
    $ (echo 1; echo1 1) 2>&1 >1.log
    bash: echo1: command not found
    $ cat 1.log
    1
    
    # 把上面的位置调换下,先把标准输出定位到1.log
    # 把标准输出定位到文件,错误输出到标准输出(此时标准输出指向文件,所以输出到文件)
    $ (echo 1; echo1 1) >1.log 2>&1
    $ cat 1.log
    1
    bash: echo1: command not found
    
    
    # /dev/null 代表空设备文件,我们经常把输出定位到/dev/null这样可以避免程序不必要的打印。
    # 这样把标准输出定位到空,再把标准错误定位到标准输出。
    $ (echo 1; echo1 1) >/dev/null 2>&1
    $
    

    linux中的标准输出和输入

    展开全文
  • 什么意思呢,或者说log4j的日志级别的优先级是什么意思呢?打个比方,如果你配置了INFO级别,那么程序中所有的DEBUG(logger.debug(xxx))级别的日志信息将不被打印出来,只会打印高于或等于所设置级别的日志,在这里...

    首先要明白的一点,也是最重要的一点:

            log4j常用的有四个级别,优先级从高到低分别是ERROR、WARN、INFO、DEBUG。什么意思呢,或者说log4j的日志级别的优先级是什么意思呢?打个比方,如果你配置了INFO级别,那么程序中所有的DEBUG(logger.debug(xxx))级别的日志信息将不被打印出来,只会打印高于或等于所设置级别的日志,在这里因为配置了INFO,那么将只会打印ERROR、WARN、INFO级别的日志到你配置的输出中。 

    下面是一个配置模板:

    log4j.rootLogger=INFO,stdout,e,w,i
    
    log4j.appender.stdout=org.apache.log4j.ConsoleAppender 
    log4j.appender.stdout.Target=System.out
    log4j.appender.stdout.Threshold = INFO
    log4j.appender.stdout.layout=org.apache.log4j.PatternLayout 
    log4j.appender.stdout.layout.ConversionPattern=[lzzcms]%d{yyyy-MM-dd HH:mm:ss} %-5p [%20c]%L\u884c: %m %n
    
    log4j.appender.i = org.apache.log4j.DailyRollingFileAppender
    log4j.appender.i.layout = org.apache.log4j.PatternLayout
    log4j.appender.i.File = ${user.home}/lzzcms/log/lzzcms_info.log
    log4j.appender.i.Threshold = INFO   
    log4j.appender.i.layout.ConversionPattern=[lzzcms]%d{yyyy-MM-dd HH:mm:ss} %-5p [%20c]%L\u884c: %m %n
    
    log4j.appender.w = org.apache.log4j.DailyRollingFileAppender
    log4j.appender.w.layout = org.apache.log4j.PatternLayout
    log4j.appender.w.File = ${user.home}/lzzcms/log/lzzcms_warn.log
    log4j.appender.w.Threshold = WARN
    log4j.appender.w.layout.ConversionPattern=[lzzcms]%d{yyyy-MM-dd HH:mm:ss} %-5p [%20c]%L\u884c: %m %n
    
    log4j.appender.e = org.apache.log4j.DailyRollingFileAppender
    log4j.appender.e.layout = org.apache.log4j.PatternLayout
    log4j.appender.e.File = ${user.home}/lzzcms/log/lzzcms_error.log
    log4j.appender.e.Threshold = ERROR
    log4j.appender.e.layout.ConversionPattern=[lzzcms]%d{yyyy-MM-dd HH:mm:ss} %-5p [%20c]%L\u884c: %m %n
    
    
    log4j.logger.cn.zhao.dao =DEBUG

    解释:

    log4j.rootLogger=INFO,stdout,e,w,i,指定程序的所有包使用log4j时打印的日志级别,这里配置为INFO,表示所有包里面低于INFO级别的日志将不被打印,即DEBUG级别不被打印,如果想指定某个包下面的debug级别打印,可以使用log4j.logger.cn.zhao.dao =DEBUG的配置方式。INFO后边的stdout,e,w,i是自己随便起的名字,如果你愿意,可以叫成abc,efg都没有关系,只是要与后边的对应起来。

    log4j.appender用于配置你定义的名字,比如log4j.appender.i。

    log4j.appender.x.Threshold=WARN:表示进入x所指定的文件的日志级别最少是WARN,那么这里低于warn级别的日志将不被输出。

    log4j.appender.x.layout.ConversionPattern用于定义日志的输出格式,%d是时间,后边的{yyyy-MM-dd HH:mm:ss}定义了时间的格式,形如“2018-01-30 21:57:57”;

    %-5p:p的意思是priority,优先级的意思,中间的5表示左对齐,因为日志级别ERROR、WARN、INFO、DEBUG,有的是5个字母的,有的是4个字母的,如果直接写%p就会对不齐,%-5p的意思是日志级别输出左对齐,右边以空格填充,%5p的意思是日志级别输出右对齐,左边以空格填充。

    %20c:c即class,表示输出全类名,包含包名,如果全类名不足20个,就用空格填补。

    %L:L表示line,行的意思,打印出在行

    %m:即message,输出代码中指定的消息,即logger.error("添加产品出现错误",e)里面的信息“添加产品出现错误”

    %n:输出一个回车换行符

    上边的都是常用的解释,经过了上边的配置,比如我有下面一段代码:

    @RequestMapping("/contentManage")
    	public String contentManage(){
    		logger.info("info级别");
    		logger.warn("warn级别");
    		logger.error("error级别");
    		return "content/contentManage";
    	}

    当请求这个路径时,对应的输出分别是:

    stdout控制台输出:

    image.png

    e的输出:

    image.png

    w的输出:

    image.png

    i的输出:

    image.png

    因为日志级别:error>warn>info>debug,又因为只会输出大于等于自己的级别的日志,所以又上边的结果,正好符合了我们上边的分析。

    展开全文
  • IO即InputStream和OutputStream,意思是输入流和输出流。 IO流 2、怎么区分输入流和输出流 刚开始学IO流的时候这个问题把我弄懵了一下 程序操作的数据都应该在内存里面,内存你操作的主对象,把数据从其他资源...

    1、什么是IO流

    IO即InputStream和OutputStream,意思是输入流和输出流。

    2、怎么区分输入流和输出流

    刚开始学IO流的时候这个问题把我弄懵了一下

    程序操作的数据都应该是在内存里面,内存是你操作的主对象,把数据从其他资源里面传送到内存里面,就是输入,反之,把数据从内存传送到其他资源,就是输出。

    读文件
    不管你从磁盘读,从网络读,或者从键盘读,读到内存,就是InputStream。数据读入到内存叫输入流。

    写文件
    不管你写倒磁盘,写到网络,或者写到屏幕,都是OuputStream。从内存写到别的地方去叫输出流。

    3、输入流的具体用法

    从文件读取内容到内存

    例子:读文件的一个字节

    read()方法是读取一个字节,返回值就是读到的数据值,如果读取的数据值等于-1,则读取到文件末尾。

    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.IOException;
    
    public class MainTest {
    	public static void main(String[] args) {
    		
    //		创建File对象
    //		File对象描述一个文件
    		File file=new File("D:\\filetest\\file1.txt"); 
    		 //!!首先得建立一个通道
    		
    		try
    		{
    //			新建一个FileInputStream对象
    			FileInputStream fileInputStream=new FileInputStream(file);
    //    !!建立通道后你得让流知道进哪个通道,因为你有可能new了几个File();
    
     //           读一个字节
    			int c1 = fileInputStream.read();
    			System.out.println(c1);//读出的是数字,是对应的ASCII码
    			int c2=fileInputStream.read();
    			System.out.println((char)c2);//读下一个字节,读出的是乱码
    			int c3=fileInputStream.read();
    			System.out.println((char)c3);
    			int c4=fileInputStream.read();
    			System.out.println((char)c4);
    			
    		}catch(FileNotFoundException e)
    		{
    			//输出堆栈信息
    			e.printStackTrace();
    		}catch(IOException e)
    		{
    			e.printStackTrace();
    		}finally {
    			
    			try {
    				//关闭输出流,释放资源
    				fileInputStream.close();
    			} catch (IOException e) {
    				e.printStackTrace();
    			}			
    		}
    	}
    }
    

    例子:输出文件里的所有内容

    创建一个数组buf
    然后用read(buf):实现从文件读取内容到内存,不会乱码,是什么就是什么

    public class HuanChongLiu {
    	public static void main(String[] args) {
    
    		// 创建File对象
    		// File对象描述一个文件
    		File file = new File("F:\\Day0730test.txt");
    /*		try {
    			file.createNewFile();  这一段代码是为了防止没有描述的文件,
    			防止程序找不到路径,有了文件的话可不要这段代码
    		} catch (IOException e1) {
    			e1.printStackTrace();
    		}
    */
    		FileInputStream fileInputStream=null;
    		try
    		{
    			//新建一个FileInputStream对象
    			fileInputStream=new FileInputStream(file);
    			
    			//新建一个字节数组,长度为32
    			byte []buf=new byte[32];
    			
    //read(buf):此方法的返回值就是当前读取的字节个数,将数据读取到buf数组
    //将readLen变量也就是read方法的返回值,当此变量等于-1,则说明读到文件末尾
    			int readLen=-1;
    			while((readLen=fileInputStream.read(buf))!=-1)//
    			{
    				//将字节数组转换成字符串
    				//String(buf,0,readLen)表示字节数组buf从第1位到
    				//第readLen位都转换成字符
    				String content=new String(buf,0,readLen);
    				System.out.print(content);//将转换承德字符输出
    			}
    		}catch(FileNotFoundException e)
    		{
    			e.printStackTrace();
    		}catch(IOException e)
    		{
    			e.printStackTrace();
    		}finally {
    			try {
    				//文件输入流关闭(释放资源)
    				fileInputStream.close();
    			} catch (IOException e) {
    				// TODO Auto-generated catchblock
    				e.printStackTrace();
    			}	
    		}
    	}
    }
    

    4、输出流的具体用法

    输出流
    将内存的数据写到文件

    例子:将多个字符写到文件中

    import java.io.File;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.IOException;
    
    public class MainTest2 {
    
    	public static void main(String[] args) {
    
    		// 通过File对象描述文件
    		File file = new File("D:\\filetest\\file3.txt");
    		// 创建FileOutputStream对象
    		FileOutputStream fileOutputStream = null;
    		try {
    			fileOutputStream = new FileOutputStream(file);
    			
    			String content="weclome to gec,I love java";
    			//将字符串转换成字节数组
    			byte []buf=content.getBytes();
    			fileOutputStream.write(buf);
    			//清除缓冲
    			fileOutputStream.flush();
    /*flush()一般主要用在IO中,即清空缓冲区数据,就是说你用读写流的时候,
    其实数据是先被读到了内存中,然后用这里的数据写到文件中,当你文件的数据
    读完的时候(即读到内存)不代表你的数据已经写完了(即写到另一个文件),
    因为还有一部分有可能会留在内存这个缓冲区中。这时候如果你调用了
    close()方法关闭了读写流,那么这部分数据就会丢失,所以应该在关闭读写流之
    前先flush(),先刷新缓存清空数据。*/    
    		} catch (FileNotFoundException e) {
    			e.printStackTrace();
    		} catch (IOException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		} finally {
    
    			try {
    				// 关闭输出流,释放资源
    				fileOutputStream.close();
    			} catch (IOException e) {
    				// TODO Auto-generated catch block
    				e.printStackTrace();
    			}
    		}
    	}
    }
    

    对于将数据写道文件,在new一个File()的时候,如果没有原文件或者路径不对,输出流会自动创建一个文件。

    5、练习题

    编写一个应用程序,将用户从键盘输入的10个整数存入文件,从文件读取再顺序读出。

    import java.io.*;
    import java.util.Scanner;
    
    public class Test {
    
        //System.in:默认是键盘设备
        public static void main(String[] args) {
    
            File file = new File("F:\\Day0730test.txt");
    		int i = 0;
    		System.out.print("请输入十个整数:");
    		@SuppressWarnings("resource")
    		Scanner scan = new Scanner(System.in);
    		FileOutputStream fileOutputStream = null;
    		//往文件写入10个整数
    		try {
    			fileOutputStream = new FileOutputStream(file);
    			 while (i < 10) {
    		            int str = scan.nextInt();//读取键盘输入
    		            fileOutputStream.write(str);//将该行写到文件中
    		            i++;
    		        }
    		} catch (FileNotFoundException e) {
    			e.printStackTrace();
    		} catch (IOException e) {
    			e.printStackTrace();
    		}
    		try {
    			fileOutputStream.close();
    		} catch (IOException e1) {
    			e1.printStackTrace();
    		}
    		//读取存入的10个整数并输出
    		FileInputStream fileInputStream = null;
    		try {
    			fileInputStream = new FileInputStream(file);
    			for(int q = 0;q<10;q++){	
    			//只读一个数据的情况:int c1 = fileInputStream.read()
    			System.out.println(fileInputStream.read());
    			}
    		} catch (FileNotFoundException e) {
    			e.printStackTrace();
    		} catch (IOException e) {
    			e.printStackTrace();
    		}
    		try {
    			fileInputStream.close();
    		} catch (IOException e) {
    			e.printStackTrace();
    		}
        }
    }
    

    6、IO流又可以分为字节流和字符流

    上面讲的FileInputStream和FileOutStream都是字节流,调用read方法读的都是一个字节,会产生乱码。
    而字符流就不会产生乱码,因为字符流调用read方法读的是一个字符。
    下面来看看字符流的使用吧

    字符流的读:FileReader

    主要方法
    在这里插入图片描述
    -------------------------------------例子---------------------------------

    public class MainTest {
    
    	public static void main(String[] args) {
    		
    		//以File对象描述file5.txt
    		File file=new File("D:\\filetest\\file5.txt");
    		//构造FileReader对象
    		FileReader reader=null;
    		try
    		{
    			reader=new FileReader(file);
    			//定义字符数组
    			char []cbuf=new char[16];
    			//定义读取字符的长度
    			int readLen=-1;
    		//不断将数据读到字符数组,read方法的返回值就是读到的字符个数,
    			//直到readLen等于-1,则意味读取文件的末尾,然后跳出循环
    			while((readLen=reader.read(cbuf))!=-1)
    			{
    				System.out.print(new String(cbuf,0,readLen));
    			}
    			
    		}catch(FileNotFoundException e)
    		{
    			e.printStackTrace();
    		} catch (IOException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}finally {
    			
    			if(reader!=null)
    			{
    				try {
    					reader.close();
    				} catch (IOException e) {
    					// TODO Auto-generated catch block
    					e.printStackTrace();
    				}
    			}
    		}
    	}
    }
    

    字符流的写:FileWriter

    主要方法
    在这里插入图片描述
    ----------------------例子----------------------------

    public class MainTest {
    
    	public static void main(String[] args) throws IOException {
    		
    		//创建文件
    		File file=new File("file2.txt");
    		FileWriter fw=new FileWriter(file);
    		
    		String message="我来自广州";
    		fw.write(message);
    		
    		/*String message="java,hello world";
    		fw.write(message);*/
    		
    		/*fw.write(0+48);
    		fw.write(1+48);
    		char cbuf[]= {'a','b'};
    		fw.write(cbuf);*/
    		fw.flush();
    		fw.close();
    	}
    }
    

    7、转换流

    InputStreamReader将字节输入流转换成字符输入流,
    OutputStreamWriter将字节输出流转换成字符输出流

    InputStreamReader

    在这里插入图片描述

    public class MainTest {
    
    	public static void main(String[] args) throws IOException {
    
    		File file = new File("file3.txt");
    		FileOutputStream fileOutputStream = new FileOutputStream(file);
    		
    		//将输出字节流---->输出字符流
    		//将数据以字符方式写到文件里面
    		OutputStreamWriter writer=new OutputStreamWriter(fileOutputStream);
    		writer.write("欢迎来到粤嵌,学习java");
    		writer.flush();
    		writer.close();
    		fileOutputStream.close();
    	}
    }
    

    OutputStreamWriter

    在这里插入图片描述

    public class MainTest {
    
    	public static void main(String[] args) throws IOException {
    
    		File file = new File("file3.txt");
    		FileOutputStream fileOutputStream = new FileOutputStream(file);
    		
    		//将输出字节流---->输出字符流
    		//将数据以字符方式写到文件里面
    		OutputStreamWriter writer=new OutputStreamWriter(fileOutputStream);
    		writer.write("欢迎来到粤嵌,学习java");
    		writer.flush();
    		writer.close();
    		fileOutputStream.close();
    	}
    }
    

    8、缓冲流

    缓冲流最大的特点是有一个缓冲区,默认分配一个8k大小的缓冲区,来储存数据,针对大量的读取及写入数据,能提高操作效率。
    在这里插入图片描述

    BufferReader类用法

    public class MainTest {
    
    	public static void main(String[] args) throws IOException {
    		
    		FileReader reader=new FileReader(new File("file4.txt"));
    		BufferedReader br=new BufferedReader(reader);
    		
    		System.out.println((char)br.read());//a
    		System.out.println((char)br.read());//b
    		//设置一个mark:标记一个位置
    		System.out.println("mark 操作");
    		br.mark(2);//reset的时候会从第3个元素开始读取,只有缓冲流能这么做,因为他有缓冲区
    		System.out.println((char)br.read());//c
    		System.out.println((char)br.read());//d
    		System.out.println("reset 操作");
    		br.reset();
    		System.out.println((char)br.read());//c
    		System.out.println((char)br.read());//d	
    		
    		//按行读取
    /*		String line1=br.readLine();
    		String line2=br.readLine();
    		String line3=br.readLine();
    		String line4=br.readLine();
    		
    		System.out.println(line1);
    		System.out.println(line2);
    		System.out.println(line3);
    		System.out.println(line4);*/
    	}
    }
    

    9、一些例子(他人代码)

    使用IO流拷贝文件

    import java.io.*;
    
    public class Copy {
    	public static void main(String[] args) {
    		//调用方法执行文件复制
    		boolean isSuccess = copyFile("要复制的文件(全路径或相对路径+文件名)","新的文件名");
    		if(isSuccess) {
    			System.out.println("文件复制成功!");
    		}else {
    			System.out.println("文件复制失败!");
    		}
    	}
    	
    	private static boolean copyFile(String oldFile, String newFile) {
    		//定义输入输出流
    		InputStream is = null;
    		OutputStream os = null;
    		StringBuilder builder = new StringBuilder();
    		try {
    			//读取
    			is = new FileInputStream(oldFile);
    			//输出
    			os = new FileOutputStream(newFile);
    			//定义字节缓冲数组
    			byte[] flush = new byte[1024];
                //定义读取长度
                int len;
                while ((len = is.read(flush)) != -1) {
                    os.write(flush, 0, len);
                }
                os.flush();
    		}  catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                //先开启的流 后关闭
                try {
                    if (null != os) {
                        os.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
                if (null != is) {
                    try {
                        is.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
            if (new File(newFile).exists()) {
                return true;
            }
            return false;
    	}
    }
    
    

    目录的拷贝

    import java.io.*;
    import java.time.Duration;
    import java.time.Instant;
    
    public class CopyDir {
        public static void main(String[] args) {
            Instant start = Instant.now();
            boolean isOk = dirOrFile("要复制的目录路径", "目标路径");
            if(isOk){
                System.out.println("目录复制完成!");
            }else {
                System.out.println("目录复制失败!");
            }
            Instant end = Instant.now();
            System.out.println("耗时:"+Duration.between(start,end).toMillis()+"毫秒!");
        }
    
    	private static boolean copyDir(String oldDir, String newDir) {
            //定义流
            InputStream is = null;
            OutputStream os = null;
            try {
                is = new FileInputStream(oldDir);
                os = new FileOutputStream(newDir);
                //定义缓冲字节数组
                byte[] flush = new byte[1024];
                //定义读取长度
                int len;
                while ((len = is.read(flush)) != -1) {
                    os.write(flush, 0, len);
                }
                //刷新流
                os.flush();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                //关闭流
                try {
                    if (null != os) {
                        os.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
                try {
                    if (null != is) {
                        is.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return false;
        }
    
    	private static boolean dirOrFile(String oldDir, String newDir) {
            //定义写入写出文件
            File old = new File(oldDir);
            File copy = new File(newDir);
            //判断如果是目录的话 创建目录
            if (old.isDirectory()) {
                copy.mkdir();
                File[] files = old.listFiles();
                for (int i = 0; i < files.length; i++) {
                    dirOrFile(files[i].getAbsolutePath(), newDir + "/" + files[i].getName());
                }
            }
            if (old.isFile()) {
                copyDir(oldDir, newDir);
            }
            if (old.length()==copy.length()){
                return true;
            }
            return false;
        }
    }
    
    

    获取文本上字符出现的字数并将数据输出到文件

    /**
     * 获取文本上字符出现的次数,把数据写入文件
     *
     * 思路:
     * 1.遍历文本每一个字符
     * 2.字符出现的次数存在Map中
     *
     * Map<Character,Integer> map = new HashMap<Character,Integer>();
     * map.put('a',18);
     * map.put('你',2);
     *
     * 3.把map中的数据写入文件
     *
     */
    public class WordCount {
      
        @Test
        public void testWordCount() {
            FileReader fr = null;
            BufferedWriter bw = null;
            try {
                //1.创建Map集合
                Map<Character, Integer> map = new HashMap<Character, Integer>();
     
                //2.遍历每一个字符,每一个字符出现的次数放到map中
                fr = new FileReader("dbcp.txt");
                int c = 0;
                while ((c = fr.read()) != -1) {
                    //int 还原 char
                    char ch = (char) c;
                    // 判断char是否在map中第一次出现
                    if (map.get(ch) == null) {
                        map.put(ch, 1);
                    } else {
                        map.put(ch, map.get(ch) + 1);
                    }
                }
     
                //3.把map中数据存在文件count.txt
                //3.1 创建Writer
                bw = new BufferedWriter(new FileWriter("wordcount.txt"));
     
                //3.2 遍历map,再写入数据
                Set<Map.Entry<Character, Integer>> entrySet = map.entrySet();
                for (Map.Entry<Character, Integer> entry : entrySet) {
                    switch (entry.getKey()) {
                        case ' ':
                            bw.write("空格=" + entry.getValue());
                            break;
                        case '\t'://\t表示tab 键字符
                            bw.write("tab键=" + entry.getValue());
                            break;
                        case '\r'://
                            bw.write("回车=" + entry.getValue());
                            break;
                        case '\n'://
                            bw.write("换行=" + entry.getValue());
                            break;
                        default:
                            bw.write(entry.getKey() + "=" + entry.getValue());
                            break;
                    }
                    bw.newLine();
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                //4.关流
                if (fr != null) {
                    try {
                        fr.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
     
                }
                if (bw != null) {
                    try {
                        bw.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
     
                }
            }
     
        }
    }
    

    10、缓冲流源码分析

    • 分析构造器
    //java的源码是不能修改的,你可以把里边的代码复制出来新建一个类。
    public MyBufferedReader(Reader in, int sz) {
            super(in);
            if (sz <= 0)
                throw new IllegalArgumentException("Buffer size <= 0");
            this.in = in;
            //自定义缓存大小
            //分配8个字符的缓存大小
            cb = new char[sz];
            //nextChar:记录下一次读取字符的位置
            //nChars:记录当前缓存区可读的字符个数
            nextChar = nChars = 0;
        }
    
    • 分析read方法
    public int read(char cbuf[], int off, int len) throws IOException {
        	//编写同步锁代码块
            synchronized (lock) {
            	//确认输入流不为空
                ensureOpen();
                if ((off < 0) || (off > cbuf.length) || (len < 0) ||
                    ((off + len) > cbuf.length) || ((off + len) < 0)) {
                    throw new IndexOutOfBoundsException();
                } else if (len == 0) {
                    return 0;
                }
                //从缓存区的数据复制到cbuf数组里面
                int n = read1(cbuf, off, len);
                if (n <= 0) return n;
                //将之前处理不完的数据复制到cbuf数组,再次调用read1方法
                while ((n < len) && in.ready()) {
                    int n1 = read1(cbuf, off + n, len - n);
                    if (n1 <= 0) break;
                    n += n1;
                }
                return n;
            }
        }
    
    • read1方法
    private int read1(char[] cbuf, int off, int len) throws IOException {
        	//nextChar:记录下一次读取字符的位置
        	//nChars:记录缓存区可读的字符个数
        	//如果nextChar>nChars,则重新刷新缓存区
            if (nextChar >= nChars) {
                /* If the requested length is at least as large as the buffer, and
                   if there is no mark/reset activity, and if line feeds are not
                   being skipped, do not bother to copy the characters into the
                   local buffer.  In this way buffered streams will cascade
                   harmlessly. */
                if (len >= cb.length && markedChar <= UNMARKED && !skipLF) {
                    return in.read(cbuf, off, len);
                }
                //针对缓存区的数据,重新刷新,将新的数据重新更新到缓存区
                fill();
            }
            if (nextChar >= nChars) return -1;
            if (skipLF) {
                skipLF = false;
                if (cb[nextChar] == '\n') {
                    nextChar++;
                    if (nextChar >= nChars)
                        fill();
                    if (nextChar >= nChars)
                        return -1;
                }
            }
            int n = Math.min(len, nChars - nextChar);
            //将缓冲区的数据复制到cbuf
            System.arraycopy(cb, nextChar, cbuf, off, n);
        	//并且更新nextChar的位置值
            nextChar += n;
            return n;
        }
    
    • fill方法
    private void fill() throws IOException {
            int dst;
            //是否有调有mark方法,如果没有设置mark值,则markedChar <= UNMARKED为true
            if (markedChar <= UNMARKED) {
                /* No mark */
                dst = 0;
            } else {
                /* Marked */
                int delta = nextChar - markedChar;
                if (delta >= readAheadLimit) {
                    /* Gone past read-ahead limit: Invalidate mark */
                    markedChar = INVALIDATED;
                    readAheadLimit = 0;
                    dst = 0;
                } else {
                    if (readAheadLimit <= cb.length) {
                        /* Shuffle in the current buffer */
                        System.arraycopy(cb, markedChar, cb, 0, delta);
                        markedChar = 0;
                        dst = delta;
                    } else {
                        /* Reallocate buffer to accommodate read-ahead limit */
                        char ncb[] = new char[readAheadLimit];
                        System.arraycopy(cb, markedChar, ncb, 0, delta);
                        cb = ncb;
                        markedChar = 0;
                        dst = delta;
                    }
                    nextChar = nChars = delta;
                }
            }
    
            int n;
            do {
            	//将输入流的数据读取到缓存区里面,n变量决定读取多个字符
                n = in.read(cb, dst, cb.length - dst);
            } while (n == 0);
            //如果n>0,代表已经读到数据
            if (n > 0) {
            	//nChars:缓存区可读的数据
                nChars = dst + n;
                //下一次可读数据的位置
                nextChar = dst;
            }
        }
    
    
    • 图如下
      缓冲区其实就是一个数组来的
      在这里插入图片描述

    11、打印流PrintStream

    PrintStream

    一般我们用System.out.println(“hellow world”);是输出到控制台的,如果我们想让他输出到其他的文件,就可以用重定向。例子如下

    这是我们之前学的:

    FileOutStream afileOutStream = new FileOutpStream(new File("a.txt"));
    //你不是要输出到a.txt吗,那就创建一个输出流,将信息输出到文件
    PrintStream ps = new PrintStream(afileOutStream);
    ps.println("你好啊");
    ps.flush();
    ps.close();
    afileOutStream.close();
    

    此时将在文件a.txt中显示 你好啊

    • 现在修改重定向设备:
      标准输出到a.txt.
    FileOutputStream afileOutStream = new FileOutputStream(new File("a.txt"));
    //你不是要输出到a.txt吗,那就创建一个输出流,将信息输出到文件
    PrintStream ps = new PrintStream(afileOutStream);
    //这里就是修改重标准输出设备了,从原本的控制台,定向到a.txt文件
    System.setOut(ps);//如果是标准错误输出,用setErr()
    System.out.println("11111");
    System.out.println("222222");
    

    PrintWrite

    public class Printstream {//类名不能与关键字同名。。。。。
    
    	public static void main(String[] args) throws FileNotFoundException {
    		
    		//获取键盘数据,用PrintStream打印输出到文件
    		FileOutputStream fileOutputStream = new FileOutputStream(new File("a.txt"));
    		PrintStream ps = new PrintStream(fileOutputStream);
    		
    		System.setOut(ps);
    		Scanner sc = new Scanner(System.in);
    		String str = sc.nextLine();
    		System.out.println(str);
    		
    		/*
    		 * 循环捕获键盘输入,当按q时结束循环
    		 * Scanner sc = new Scanner(System.in);
    		 * String content = null;
    		 * while((content=sc.nextLine())!=null){
    		   		System.out.println(content);
    		   		if(content.equals("q")){  //如果键盘输入q则结束循环
    		   			break;
    		  		 }
    		   }
    		   sc.close();//关闭资源
    		 */
    		
    		
    		
    		
    		//获取键盘数据,用PrintWrite打印输出到文件
    		FileOutputStream a = new FileOutputStream(new File("b.txt"));
    		PrintWriter pw = new PrintWriter(a);
    		
    		Scanner sr = new Scanner(System.in);
    		String st = sr.nextLine();
    		pw.write(st);
    		pw.flush();
    		pw.close();
    		sr.close();
    	}
    }
    

    12、一个强大的读写文件的类RandomAccessFile(不属于IO流体系但可以任意读取文件)

    • RandomAccessFile类的最大特点就是可以自由访问文件的任意位置(用seek()方法),支持字节、字符操作
    • 例子
    package RandomAccessFile实例;
    
    import java.io.File;
    import java.io.FileNotFoundException;
    import java.io.IOException;
    import java.io.RandomAccessFile;
    
    public class MainTest {
    
    	public static void main(String[] args) throws IOException {
    		
    		//创建一个File对象
    		File file=new File("f.txt");
    		
    		RandomAccessFile randomAccessFile=new RandomAccessFile(file, "rw");
    		System.out.println((char)randomAccessFile.read());
    		//将读取的起始位置定位到第4个字符开始读取
    		System.out.println("将读取的起始位置定位到第4个字符开始读取,调用seek(3)");
    		randomAccessFile.seek(3);
    		System.out.println((char)randomAccessFile.read());
    		System.out.println((char)randomAccessFile.read());
    		System.out.println((char)randomAccessFile.read());
    		System.out.println((char)randomAccessFile.read());
    		System.out.println("将读取的起始位置定位到第4个字符开始读取,调用seek(3)");
    		randomAccessFile.seek(3);
    		System.out.println((char)randomAccessFile.read());
    		System.out.println((char)randomAccessFile.read());
    		System.out.println((char)randomAccessFile.read());
    		System.out.println((char)randomAccessFile.read());
    		
    		//读取行数
    		System.out.println(randomAccessFile.readLine());
    		System.out.println(randomAccessFile.readLine());
    		System.out.println(randomAccessFile.readLine());
    		System.out.println(randomAccessFile.readLine());
    
    	}
    
    }
    
    

    13、对象流:对象序列化处理

    (1)什么是序列化、反序列化

    • 把对象转换为字节序列的过程称为对象的序列化。序列化后存到文件以保存它的信息。存到文件所以是输出流,用writeObject。

    • 把字节序列恢复为对象的过程称为对象的反序列化。

    • 对象的序列化主要有两种用途

    ··· 1) 把对象的字节序列永久地保存到硬盘上(这样就可以把对象的信息保存起来了),通常存放在一个文件中;
      2) 在网络上传送对象的字节序列。

    在很多应用中,需要对某些对象进行序列化,让它们离开内存空间,入住物理硬盘,以便长期保存。比如最常见的是Web服务器中的Session对象,当有 10万用户并发访问,就有可能出现10万个Session对象,内存可能吃不消,于是Web容器就会把一些session先序列化到硬盘中,等要用了,再把保存在硬盘中的对象还原到内存中。当两个进程在进行远程通信时,彼此可以发送各种类型的数据。
      无论是何种类型的数据,都会以二进制序列的形式在网络上传送。发送方需要把这个Java对象转换为字节序列,才能在网络上传送;接收方则需要把字节序列再恢复为Java对象。
      举个真实的案例:当我们需要使用的对象很复杂或者需要很长时间去构造,这时就会引入使用代理模式(Proxy)。例如:如果构建一个对象很耗费时间和计算机资源,代理模式(Proxy)允许我们控制这种情况,直到我们需要使用实际的对象。一个代理(Proxy)通常包含和将要使用的对象同样的方法,一旦开始使用这个对象,这些方法将通过代理(Proxy)传递给实际的对象。

    • 可通过对象输出流(ObjectOutputStream)将对象序列化,然后通过对象输入流(ObjectInputStream)恢复对象

    • java.io. Serializable接口用来作为实现对象序列化的工具 ,接口中没有任何方法。当一个类声明实现Serializable接口后,表明该类可被序列化。

    • 注意:
      1、序列化只能保存对象的非静态成员变量,而且只保存变量的值,不能保存任何的成员方法和静态的成员变量,对于变量的任何修饰符都不能保存。
      2、数组和集合对象是可以直接被序列化存储的。
      3、为了解决类的版本问题,可配合使用serialVersionUID成员。

    (2)对象序列化实例

    package 对象序列化处理;
    
    import java.io.Serializable;
    
    /*
     * 此类对象为要序列化处理的对象
     */
    public class Person implements Serializable { //要序列化的对象对应的类要实现Serializable接口
    	
    	private String name;//私有化属性,下面提供gette,setter方法,有参和无参构造方法。
    	private Integer age;
    	
    	public Person() {
    		
    	}
    	
    	public Person(String name, Integer age) {
    		this.name = name;
    		this.age = age;
    	}
    	public String getName() {
    		return name;
    	}
    	public void setName(String name) {
    		this.name = name;
    	}
    	public Integer getAge() {
    		return age;
    	}
    	public void setAge(Integer age) {
    		this.age = age;
    	}
    	
    	@Override
    	public String toString() {
    		return "Person [name=" + name + ", age=" + age + "]";
    	}
    }
    
    package 对象序列化处理;
    public class MainTest {
    
    	public static void main(String[] args) throws IOException {
    		
    		//序列化:将一个类的对象序列化成字节序列,保存到磁盘文件
    		//创建一个输出流的文件
    		FileOutputStream fileOutputStream=new FileOutputStream(new File("person.txt"));
    		//ObjectOutputStream针对此fileOutputStream进行处理
    		ObjectOutputStream os=new ObjectOutputStream(fileOutputStream);
    		
    		//创建Person对象
    		Person p=new Person();
    		p.setName("xiaoming");
    		p.setAge(30);
    		
    		os.writeObject(p);
    		
    		os.close();
    		fileOutputStream.close();
    	}
    }
    

    反序列化实例

    package 对象反序列化处理;
    import 对象序列化处理.Person;
    
    public class MainTest {
    
    	public static void main(String[] args) throws IOException, ClassNotFoundException {
    		
    		//创建读取文件的输入流对象
    		FileInputStream fileInputStream=new FileInputStream(new File("person.txt"));
    		//创建一个读取对象的输入流对象,读取person.txt文件
    		ObjectInputStream os=new ObjectInputStream(fileInputStream);
    		//反序列成一个对象
    		Person p=(Person) os.readObject();
    		
    		System.out.println("用户名="+p.getName());
    		System.out.println("年龄="+p.getAge());
    		
    		os.close();
    		fileInputStream.close();
    	}
    }
    

    transient关键字

    • 用法:如果使用transient关键字修饰成员变量,则此变量忽略序列化处理。反序列化时会给这个transient修饰的变量对应类型的默认值。

    14、自定义序列化处理

    可以自定义实现序列化逻辑处理。

    (1)具体实现

    在序列化对象类重写:readObject和writeObject方法

    • writeObject:编写自定义序列化处理的逻辑

    • readObject:编写自定义反序列化处理的逻辑

    有时候,可能是由于独特的序列化需求、性能方面的考虑又或是希望在对象反序列化后能够执行其他操作,我们需要重写这个默认的序列化实现。这时候,我们可以通过如下两个方法来实现。

    • private void writeObject(ObjectOutputStream out) throws IOException
    • private void readObject(ObjectInputStream in) throws ClassNotFoundException, IOException
    package 自定义序列化处理;
    
    import java.io.IOException;
    import java.io.Serializable;
    
    public class Person implements Serializable {
    	
    	private String name;
    	private Integer age;
    	
    	
    	public Person() {
    		super();
    	}
    	public Person(String name, Integer age) {
    		this.name = name;
    		this.age = age;
    	}
    	/**
    	 * @return the name
    	 */
    	public String getName() {
    		return name;
    	}
    	/**
    	 * @param name the name to set
    	 */
    	public void setName(String name) {
    		this.name = name;
    	}
    	/**
    	 * @return the age
    	 */
    	public Integer getAge() {
    		return age;
    	}
    	/**
    	 * @param age the age to set
    	 */
    	public void setAge(Integer age) {
    		this.age = age;
    	}
    	/* (non-Javadoc)
    	 * @see java.lang.Object#toString()
    	 */
    	@Override
    	public String toString() {
    		return "Person [name=" + name + ", age=" + age + "]";
    	}
    	
    	/*
    	 * 通过重写此方法,自定义反序列化逻辑 (从字节序列文件读取还原对象状态)
    	 * */
    	private void readObject(java.io.ObjectInputStream in) throws Exception
    	{
    		//以大写字母输出用户名
    		setName(in.readUTF().toUpperCase());
    		setAge(in.readInt());
    	}
    	
    	/*
    	 * 通过重写此方法,自定义序列化逻辑(序列化:将对象序列化成字节序列,存储到磁)
    	 * */
    	private void writeObject(java.io.ObjectOutputStream out) throws IOException
    	{
    		//将用户名序列化
    		out.writeUTF(getName());
    		//将年龄序列化
    		out.writeInt(getAge());
    	}
    }
    
    展开全文
  • 另外问一下start.bat最后一行`call "%EXECUTABLE%" start %CMD_LINE_ARGS%`改成`call "%EXECUTABLE%" run %CMD_LINE_ARGS%`是什么意思,麻烦详细说说,谢谢 下面是tomcat中`logging.properties`配置(没改过) ...
  • Linux echo的 > 和 >>

    千次阅读 2020-09-14 09:37:51
    echo >...输出重定向把echo的参数输出到某个文件(而不是输出到终端,这就是输出重定向)。 echo > >输出追加重定向 操作符>>输出追加重定向和>输出重定向功能类似。 相同的地方:如
  • 是什么意思? 我该做什么? E.6.11 在安装时, Linux无法工作在我的Ultra DMA IDE驱动器和主机板上, 怎么办? E.6.12 我的机器有一个PCI Ultra DMA 控制器. 我可以安装Linux吗? E.6.13 我有NT, 并想安装Linux, 但...
  • Linux从入门精通

    2010-04-25 19:58:09
    是什么意思? 我该做什么? E.6.11 在安装时, Linux无法工作在我的Ultra DMA IDE驱动器和主机板上, 怎么办? E.6.12 我的机器有一个PCI Ultra DMA 控制器. 我可以安装Linux吗? E.6.13 我有NT, 并想安装Linux, 但...
  • 上面命令的意思是将command代码过程中打印的标准输出和标准错误代码一并重定向至log文件中。   Q:那什么是标准输出和标准错误,什么是重定向,标准输出和标准错误又有什么区别呢?下面一一揭晓: 1. 标准输出和...
  • linux从入门精通.chm

    2010-05-17 09:11:20
    是什么意思? 我该做什么? E.6.11 在安装时, Linux无法工作在我的Ultra DMA IDE驱动器和主机板上, 怎么办? E.6.12 我的机器有一个PCI Ultra DMA 控制器. 我可以安装Linux吗? E.6.13 我有NT, 并想安装Linux, 但...
  • 《Linux从入门精通》

    热门讨论 2008-09-04 17:05:49
    是什么意思? 我该做什么? E.6.11 在安装时, Linux无法工作在我的Ultra DMA IDE驱动器和主机板上, 怎么办? E.6.12 我的机器有一个PCI Ultra DMA 控制器. 我可以安装Linux吗? E.6.13 我有NT, 并想安装Linux, 但...
  • 标准io

    2017-09-01 22:02:27
    在这么我们不能认为输入输出就是用鼠标键盘写东西,再从文件打印东西屏幕上,而是对于流的操作,流入流出。 在linux系统里有一句话叫做,everything is file,一切皆文件 意思是你所看到的都
  • logback实践笔记

    2019-01-08 18:42:00
    ​ 每次看公司配置好的logback文件的时候,都不知道什么意思。导致有的时候,一些项目发测试环境的时候,有的项目没有打印日志,自己都不知道哪里有问题。所以自己新建一个springboot项目,使用logback来打印日志...
  • 上面的-a和-o分别是什么意思呢?通过查找官网相关资料,整理出下面的列表参数说明: 标记描述-o指定输出文件。-a强行对所有涉及的代码包(包括标准库中的代码包)进行重新构建,即使它们已经是最新的了。-n打印...
  • 你必须知道的495个C语言问题

    千次下载 热门讨论 2015-05-08 11:09:25
    3.20 “semanticsof‘’changeinANSIC”的警告是什么意思? 3.21 “无符号保护”和“值保护”规则的区别在哪里? 第4章 指针 基本的指针应用 4.1 指针到底有什么好处? 4.2 我想声明一个指针并为它分配...
  • 是什么意思? 在本课程的前面,我们向您介绍了Xcode,我们将在后续课程中对其进行更详细的介绍。 现在,知道该实验室正在要求您打开一个操场文件,我们将逐步指导您完成这些步骤。 游乐场文件中没有测试。 首先...
  • 今天我们继续来学习每天一个命令,今天我们进入了这章内容:文件和目录命令(FILE AND DIRECTORY COMMANDS),今天学习的是什么命令呢,那就是head(将每个文件的前10行打印到标准输出。)由于此命令较为简单,我们...
  • 《你必须知道的495个C语言问题》

    热门讨论 2010-03-20 16:41:18
    3.20 “semantics of‘’change in ANSI C”的警告是什么意思? 42 3.21 “无符号保护”和“值保护”规则的区别在哪里? 42 第4章 指针 45 基本的指针应用 45 4.1 指针到底有什么好处? 45 4.2 我想声明...
  • o 2.4 extern 在函数声明中是什么意思? o 2.5 关键字 auto 到底有什么用途? o 2.6 我似乎不能成功定义一个链表。我试过 typedef struct { char *item; NODEPTR next; } *NODEPTR; 但是编译器报了错误信息。难道...
  • 3.20 “semantics of‘’change in ANSI C”的警告是什么意思? 42 3.21 “无符号保护”和“值保护”规则的区别在哪里? 42 第4章 指针 45 基本的指针应用 45 4.1 指针到底有什么好处? 45 4.2 我想声明...
  • java面试宝典

    2013-02-28 16:04:01
    47、在java 中一个类被声明为final 类型,表示了什么意思? 12 48、下面哪些类可以被继承? 12 49、指出下面程序的运行结果: 【基础】 13 52、关于内部类: 13 53、数据类型之间的转换: 14 54、字符串操作:如何实现...
  • 千方百计笔试题大全

    2011-11-30 21:58:33
    47、在java 中一个类被声明为final 类型,表示了什么意思? 12 48、下面哪些类可以被继承? 12 49、指出下面程序的运行结果: 【基础】 13 52、关于内部类: 13 53、数据类型之间的转换: 14 54、字符串操作:如何实现...
  • 3.20 “semantics of‘>’change in ANSI C”的警告是什么意思? 71 3.21 “无符号保护”和“值保护”规则的区别在哪里? 71 第4章 指针 74 基本的指针应用 74 4.1 指针到底有什么好处? 74 4.2 我想声明一个...
  • 3.20 “semantics of‘>’change in ANSI C”的警告是什么意思? 71 3.21 “无符号保护”和“值保护”规则的区别在哪里? 71 第4章 指针 74 基本的指针应用 74 4.1 指针到底有什么好处? 74 4.2 我想声明一个...
  • 1.11 extern在函数声明中是什么意思? 1.12 关键字auto到底有什么用途? 类型定义(typedef)  1.13 对于用户定义类型,typedef和#define有什么区别? 1.14 我似乎不能成功定义一个链表。我试过typedefstruct{...
  •  1.11 extern在函数声明中是什么意思? 1.12 关键字auto到底有什么用途? 类型定义(typedef) 1.13 对于用户定义类型,typedef和#define有什么区别? 1.14 我似乎不能成功定义一个链表。我试过typedefstruct{...

空空如也

空空如也

1 2 3 4
收藏数 77
精华内容 30
关键字:

打印输出到文件是什么意思