第七周

20145113第七周学习总结

教材学习内容

一、时间与日期

1.Date

直接输出显示当前时间,但是格式说不是很友好

于是使用SimpleDateFormat显示我们需要的格式

也可以将我们的格式2016年04月18日 18:03:28:28一个字符串转化为默认格式

2.Calendar

	Calendar c= Calendar.getInstance();
    int year=c.get(Calendar.YEAR);
    int month=c.get(Calendar.MONTH);
    int day=c.get(Calendar.DAY_OF_MONTH);
    int hour=c.get(Calendar.HOUR_OF_DAY);
    int mi=c.get(Calendar.MINUTE);
    int second=c.get(Calendar.SECOND);
    System.out.println(year+"年"+month+"月"+day+"日"+" "+hour+":"+mi+":"+second);

创建对象的时候需要注意,是静态的方法,并且获得的月份是从0开始的。Date date=c.getTime();也可以用getTime()获得Date对象。

二、输入/输出

上周在看到这章的时候有些抵触情绪,就没怎么认真学习了,在老师强调这章很重要后,我决定重新学习这章的知识
####编码

  • Java是双字节编码 utf-16be,中文英文都是占用两个字节。
  • Integer.toHexString();是将字节转换成了int,以16进制的方式显示(32位,可以&0xff)。
  • byte[]bytes1=s.getBytes();将字符串转化为字节序列,也可以byte[]bytes1=s.getBytes("gbk")制定某种编码。
  • 项目默认的是gbk编码,中文占用2个字节,英文占用1个字节
  • utf-8,中文占用3个字节,英文占用1个字节
当字节序列按某种编码时,如果这个时候想把字节序列转换为字符串,则也得用这种编码,否则则会乱码。文本文件,就是字节序列,可以是任意编码的字节序列。在中文机器上直接创建文本文件,该文本文件只认识ansi编码。但文本文件本身可以放各种编码。 ####文本与文本文件
  • java中的文本(char)是16位无符号整数,是字符的unicode编码(双字节编码)
  • 文件是byte byte byte...的数据序列
  • 文本文件是文本(char)序列按照某种编码序列化为byte的存储结果
####File 1.File类只用于表示文件(目录)的信息(名称、大小),不能用于文件内容的访问
2.File类基本API操作
 file.exists();//判断文件是否存在
 file.mkdir();//创建文件
 file.delete();//删除文件
 file.isDirectory();//是否是一个目录
 file.isFile();//是否是一个文件

上面的file.mkdir()创建的是文件夹,如果想创建.txt文件

File file1=new File("D:\java\after\txt.txt");
    try {
        file1.createNewFile();
    } catch (IOException e) {
        e.printStackTrace();
    }

是需要捕捉IO异常的。

    System.out.println(file1);     //file.toString()内容
    System.out.println(file1.getAbsoluteFile());
    System.out.println(file1.getAbsolutePath());
    System.out.println(file1.getName());
    System.out.println(file1.getParentFile());

列出某个文件下的所有文件名

        String []filenames=dir.list();
    for(String s:filenames)
    {
        System.out.println(s);
    }

但是返回的是字符串,要遍历子目录下的内容,就要再转换。使用File[] files=dir.listFiles();就可以避免这个麻烦然后可以使用递归的方式遍历所有子目录与子目录下的所有文件

File[] files=dir.listFiles();
    if(files!=null&&files.length>0)
    {
        for(File file:files)
        {
            if(file.isDirectory())
                listt(file);
            else 
            System.out.println(file);

        }
    } 

RandomAccessFile

java提供的对文件内容的访问,既可以读文件也可以写文件,支持随机访问文件,可以访问文件的任何位置
对文件进行写入

 File file=new File("document");
    if(!file.exists())
        file.mkdir();
    File file1=new File("document","hello.txt");
    if(!file1.exists())
        file1.mkdir();
        RandomAccessFile randomAccessFile=new RandomAccessFile(file1,"rw");
    System.out.println(randomAccessFile.getFilePointer());
    int i =0x7;
    randomAccessFile.writeInt(i);
    System.out.println(randomAccessFile.getFilePointer());
}

对文件的读取

    randomAccessFile.seek(0);
    int i=0x7;
    randomAccessFile.writeInt(i);
    int j='A';
    randomAccessFile.writeInt(j);
    String s="中";
    byte[]b=s.getBytes("gbk");
    randomAccessFile.write(b);
    System.out.println(randomAccessFile.length());
    randomAccessFile.seek(0);
    byte[]buf=new byte[(int)randomAccessFile.length()];
    randomAccessFile.read(buf);
    System.out.println(Arrays.toString(buf));
    for(byte t:buf)
    {
        System.out.println(Integer.toHexString(t&0xff)+"  ");
    }
    System.out.println();
 randomAccessFile.close();
}

FileInputStream与FileOutputStream

FileInputStream具体实现了在文件上读取数据。

FileOutputStream实现了向文本文件中写出byte数据的方法。

FileOutputStream file=new FileOutputStream("");文件不存在的话则会直接创建文件,如果不存在则会删除后创建。如果加上true则会追加。

DataInputStream与DataOutputStream

FileInputStream inn=new FileInputStream(file1);
DataInputStream in=new DataInputStream(inn);

是嵌套出来的。自动在指定的类型与字节间的转换。

字符流(Reader Writer)

字符的处理,一次处理一个字符。

InputStreamReader完成byte流解析为char流,按照编码解析

OutputStreamWr完成char流解析为byte流,按照编码处理

构造的时候也是嵌套构造的。

代码调试过程中的问题和解决过程

线程

上周的能量转移中遇到的问题继续解决

public  void transfer(int from,int to,double amount)
{
    if(energyBoxs[from]<amount)
        return;
    energyBoxs[from]=energyBoxs[from]-amount;
    System.out.printf("%s 从%d转移%7.2f单位能量到%d
",Thread.currentThread().getName(), from, amount, to);
    System.out.println("hello
");
    energyBoxs[to]=energyBoxs[to]+amount;
    System.out.printf("能量总和:%f
", getTotalEnergy());
}

会发现当一个线程在执行的时候完一条语句后即使没有休眠,其它线程也可以插入执行。可由程序结果直观看出,当所有线程都开始工作的时候,第一个开始执行的线程输出了转移情况在还没输出能量总和的时候其它线程就开始执行了,就会导致程序结果显示,有连续的几个输出能量转移情况,却只出现一条能量总和,而且由于能量争用导致能量不守恒。 使用了synchronized

private final Object lockObj=new Object();
public  void transfer(int from,int to,double amount)
{
    synchronized (lockObj)
    {
        if(energyBoxs[from]<amount)
            return;

        ...

        lockObj.notifyAll();
    }

}

lockObj.notifyAll()在执行完这个线程后,让其它线程开始。
开始写的时候,认为只要转移的能量大于本身的能量就退出,但是考虑到这样的线程退出后还会跟其它线程争抢CPU的执行,所以进行优化。

 while (energyBoxs[from]<amount)
{
    try {
        lockObj.wait();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

使用了lockObj.wait()将线程挡在外面。

互斥——关键数据在同一时间只能被一个线程访问。使用了synchronized ()给数据块加锁。

同步——wait()/notify()/notifyAll()

思考与总结

刚开始对输入输出部分看得很头疼,上一周看的时候也只是草草看完,基础特别薄弱,虽然这周着重看了这部分的,比上周好多了,但是可能还需要对一些概念进行更深入的理解。对于线程那部分,上星期就遗留下来很多问题,虽然解决了一部分,但是还存在一部分需要这周继续完成。

学习进度条

代码行数(新增/累积) 博客量(新增/累积) 学习时间(新增/累积) 重要成长
目标 5000 25 100
第一周 100/200 1/2 3/5
第二周 300/400 1/3 4/9 使用everything与PowerCmd
第三周 200/600 1/3 8/17 安装了idea,并将代码上传到gitosc上
第四周 400/1000 1/4 15/32
第五周 800/1800 2/6 20/52
第六周 1000/2800 1/7 20/72
原文地址:https://www.cnblogs.com/crystallin/p/5401284.html