Java對文件的操作及UDP,TCP

1.文本文件復(fù)制

/*
將C盤下的一個文本文件復(fù)制到D盤下。
其實就是將C盤下的文件數(shù)據(jù)存儲到D盤下的一個文件中

步驟:
1.在D盤中創(chuàng)建一個文件,用于存儲C盤文件中的數(shù)據(jù)。
2.定義讀取流和C盤文件關(guān)聯(lián)
3.通過不斷的讀寫完成數(shù)據(jù)存儲。
4.關(guān)閉資源。
*/
//方法一
import java.io.*;
class CopyText {
    public static void main(String[] args) throws IOException{
        copy();
    }
    public static void copy(){
        FileReader fr = null;
        FileWriter fw = null;
        try{
            fr = new FileReader("c:\\demo.txt");
            fw = new FileWriter("d:\\demoD.txt",true);

            char[] buf = new char[1024];
            int len = 0;
            while((len=fr.read(buf))!=-1){
                fw.write(buf,0,len);
            }
        }catch (IOException e){
            throw new RuntimeException("讀寫失敗");
        }finally{
            if(fr!=null)
            try{
                fr.close();
            }catch (IOException e){
                System.out.println(e.toString());
            }

            if(fw!=null)
            try{
                fw.close();
            }catch (IOException e){
                System.out.println(e.toString());
            }
        }
    }
}

//方法二
/*
通過緩沖區(qū)復(fù)制一個文本文件。
*/
import java.io.*;
class CopyTextByBuf{
    public static void main(String[] args){
        BufferedWriter bufw = null;
        BufferedReader bufr = null;
        try
        {
            bufw = new BufferedWriter(new FileWriter("e:\\bufD.txt",true)); 
            bufr = new BufferedReader(new FileReader("c:\\buf.txt")); 
            
            String line = null;//相當(dāng)于中轉(zhuǎn)站。
            while((line=bufr.readLine())!=null)
            {
                bufw.write(line);
                bufw.newLine();
                bufw.flush();
            }

        }
        catch (IOException e)
        {
            throw new RuntimeException("讀寫失敗");
        }
        finally
        {
            if(bufw!=null)
            try
            {
                bufw.close();
            }
            catch (IOException e)
            {
                throw new RuntimeException("寫入關(guān)閉失敗");
            }

            if(bufr!=null)
            try
            {
                bufr.close();
            }
            catch (IOException e)
            {
                throw new RuntimeException("讀取關(guān)閉失敗");
            }
        }
    }
}

2.二進(jìn)制文件(圖片,視頻等)復(fù)制

/*
復(fù)制一個圖片(不要拿字符流處理媒體文件,字符流只處理文字?jǐn)?shù)據(jù))

思路:
1.用字節(jié)讀取流對象和圖片關(guān)聯(lián)
2.用字節(jié)寫入流對象創(chuàng)建一個圖片文件,用于存儲獲取到的圖片數(shù)據(jù)。
3.通過循環(huán)讀寫,完成數(shù)據(jù)的存儲
4.關(guān)閉資源。
*/

import java.io.*;
class  CopyPic
{
    public static void main(String[] args)
    {
        FileOutputStream fos = null;
        FileInputStream fis = null;
        try
        {
            fos = new FileOutputStream("CopyofSrc.png");
            fis = new FileInputStream("src.jpg");

            byte[] buf = new byte[fis.available()];//定義一個剛剛好的緩沖區(qū),不用再循環(huán)了。
            int len = 0;
            while((len = fis.read(buf))!=-1)
            {
                fos.write(buf);
            }
        }
        catch (IOException e)
        {
            throw new RuntimeException("讀寫失敗");
        }
        finally
        {
            try
            {
                if(fos!=null)
                    fos.close();
            }
            catch (IOException e)
            {
                throw new RuntimeException("寫入失敗");
            }
            try
            {
                if(fis!=null)
                    fis.close();
            }
            catch (IOException e)
            {
                throw new RuntimeException("讀取失敗");
            }
        }   
    }
}

3.標(biāo)準(zhǔn)鍵盤讀取/標(biāo)準(zhǔn)控制臺輸出

//讀取鍵盤輸入的最常見寫法。
BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
//寫入控制臺的最常用寫法。
BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out));

4.UDP

/*
編寫一個聊天程序
有收數(shù)據(jù)的部分和發(fā)數(shù)據(jù)的部分
這兩部分需要同時執(zhí)行,那就需要用到多線程技術(shù),
一個線程控制接收,一個線程控制發(fā)送。

因為收和發(fā)動作是不一致的,所以要定義兩個run方法,
而且這兩個方法要封裝到不同的類中。

*/

import java.io.*;
import java.net.*;
class Send implements Runnable
{
    private DatagramSocket ds ;
    public Send(DatagramSocket ds)
    {
        this.ds = ds;
    }
    public void run()
    {
        try
        {
            BufferedReader bufr = 
                new BufferedReader(new InputStreamReader(System.in));
            String line = null;
            while((line = bufr.readLine())!= null)
            {
                if("886".equals(line))
                    break;
                byte[] buf = line.getBytes();
                DatagramPacket dp = new DatagramPacket(buf,buf.length,InetAddress.getByName("localhost"),10003);
                
                ds.send(dp);
            }
        }
        catch (Exception e)
        {
            throw new RuntimeException("發(fā)送端失敗");
        }
    }
}

class Rece implements Runnable
{
    private DatagramSocket ds ;
    public Rece(DatagramSocket ds)
    {
        this.ds = ds;
    }
    public void run()
    {
        try
        {
            while(true)
            {
                byte[] buf = new byte[1024*64];
                DatagramPacket dp = new DatagramPacket(buf,buf.length);

                ds.receive(dp);

                String ip = dp.getAddress().getHostAddress();
                String data = new String(dp.getData(),0,dp.getLength());

                System.out.println(ip+":"+data);
            }
        }
        catch (Exception e)
        {
            throw new RuntimeException("接收端失敗");
        }   
    }   
}

class ChatDemo //必須掌握 
{
    public static void main(String[] args) throws Exception
    {
        DatagramSocket sendSocket = new DatagramSocket();
        DatagramSocket receSocket = new DatagramSocket(10003);

        new Thread(new Send(sendSocket)).start();
        new Thread(new Rece(receSocket)).start();
    }
}

5.TCP

/*
需求:客戶端并發(fā)上傳圖片

*/
/*
客戶端
1.服務(wù)端點
2.讀取客戶端已有的圖片數(shù)據(jù)
3.通過socket輸出流將數(shù)據(jù)發(fā)給服務(wù)端
4.讀取服務(wù)端反饋信息
5.關(guān)閉
*/
import java.io.*;
import java.net.*;
class  UploadPicClient
{
    public static void main(String[] args) throws IOException
    {
        //主函數(shù)傳參數(shù)  java UploadPicClient c:\1.png
        if(args.length!=1)
        {
            System.out.println("請選擇一個jpg格式的圖片文件");
            return;
        }

        File file = new File(args[0]);
        if(!(file.exists()&&file.isFile()))
        {
            System.out.println("上傳的文件不存在或者不是文件");
            return ;
        }
        if(!(file.getName().endsWith(".png")))
        {
            System.out.println("上傳的文件格式不正確,請重新選擇!");
            return;
        }
        if(file.length()>1024*1024*5)
        {
            System.out.println("文件過大,不安好心,重新選擇 !");
            return;
        }


        Socket s = new Socket("localhost",50005);
        
        FileInputStream in = new FileInputStream(file);

        OutputStream out = s.getOutputStream();

        byte[] buf = new byte[1024];
        int len = 0 ;
        while((len = in.read(buf))!=-1)
        {
            out.write(buf,0,len);
        }
        //告訴服務(wù)器數(shù)據(jù)寫完了。
        s.shutdownOutput();

        InputStream is = s.getInputStream();

        byte[] bufIn = new byte[1024];
        int num = is.read(bufIn);
        
        System.out.println(new String(bufIn,0,num));

        s.close();
        in.close();
    }
}


/*
服務(wù)端
這個服務(wù)端有個局限性,當(dāng)A客戶端連接上以后,被服務(wù)端獲取到,服務(wù)端執(zhí)行具體流程。
這時B客戶端連接,只有等待
因為服務(wù)端還沒有處理完A客戶端的請求,還要循環(huán)回來執(zhí)行下次accept方法,所以
暫時獲取不到B客戶端對象。

那么為了可以讓多個客戶端同時并發(fā)訪問服務(wù)端,
那么服務(wù)端最好就是將每個客戶端封裝到一個單獨的線程中,這樣,就可以
同時處理多個客戶端請求。

如何定義線程呢?
只要明確了每一個客戶端要在服務(wù)端執(zhí)行的代碼即可,將該代碼存入run方法中。

*/

class PicThread implements Runnable
{
    private Socket s ;
    PicThread(Socket s )
    {
        this.s = s;
    }
    public void run()
    {
        String ip = s.getInetAddress().getHostAddress();
        int num = 1;//只能定義在函數(shù)內(nèi),在外的話是共享數(shù)據(jù),不行的。
        try
        {
            System.out.println(ip+".....connected");

            InputStream in = s.getInputStream();

            File file = new File("d:\\server.png");
            while(file.exists())
                file = new File("d:\\server("+(num++)+").png");

            FileOutputStream out = new FileOutputStream(file);

            byte[] buf = new byte[1024];
            int len = 0 ;
            while((len = in.read(buf))!=-1)
            {
                out.write(buf,0,len);
            }

            OutputStream os = s.getOutputStream();
            os.write("上傳圖片成功??!".getBytes());


            out.close();
            s.close();  
        }
        catch (Exception e)
        {
            throw new RuntimeException(ip+"上傳失敗^_^");
        }
    }
}

class  UploadPicServer
{
    public static void main(String[] args) throws IOException
    {
        ServerSocket ss = new ServerSocket(50005);
        while(true)
        {
            Socket s = ss.accept();
            new Thread(new PicThread(s)).start();//服務(wù)器多線程玩法,幾乎所有服務(wù)器都這么玩。
        }
    }
}

6.多線程實現(xiàn)方式

//方法一:
/*
創(chuàng)建兩個線程,和主線程交替運行

線程都有自己默認(rèn)的名稱
Thread-編號  該編號從0開始

static Thread currentThread():獲取當(dāng)前線程對象。
getName():獲取線程名稱。

設(shè)置線程名稱:setName或者通過構(gòu)造函數(shù)
*/

class Test extends Thread
{
    public Test(String name)
    {
        super(name);//通過構(gòu)造函數(shù)給線程取名。
    }
    public void run(){
        for(int x = 0;x <10;x++)
        {
            System.out.println((Thread.currentThread()==this)+"...."+this.getName()+"run..."+x);
        }
    }
}
class  ThreadTest
{
    public static void main(String[] args) 
    {
        Test t1 = new Test("one----");
        Test t2 = new Test("two++++");
        t1.start();
        t2.start();
        for(int i = 0 ;i<20;i++)
            System.out.println("hello world"+i);
    }
}


//方法二
class Ticket implements Runnable
{
    private int tick = 10;
    public void run()
    {
        while(true)
        {
            if(tick>0)
            {
                System.out.println(Thread.currentThread().getName()+"sale:"+tick--);
            }
        }
    }
}
class  TicketDemo
{
    public static void main(String[] args) 
    {
        Ticket t = new Ticket();

        Thread t1 = new Thread(t);
        Thread t2 = new Thread(t);
        Thread t3 = new Thread(t);
        Thread t4 = new Thread(t);
        t1.start();
        t2.start();
        t3.start();
        t4.start();

    }
}

7.死鎖/線程間通信

/*
死鎖程序經(jīng)典案例。面試可以用

*/

class Test implements Runnable
{
    private boolean flag;
    Test(boolean flag)
    {
        this.flag = flag;
    }
    public void run()
    {
        if(flag)
        {
            while(true)
            {
                synchronized(MyLock.locka)
                {
                    System.out.println("if locka");
                    synchronized(MyLock.lockb)
                    {
                        System.out.println("if lockb");
                    }
                }
            }
        }
        else
        {
            while(true)
            {
                synchronized(MyLock.lockb)
                {
                    System.out.println("else lockb");
                    synchronized(MyLock.locka)
                    {
                        System.out.println("else locka");
                    }
                }
            }
        }
    }
}

class MyLock
{
    static Object locka = new Object();
    static Object lockb = new Object();
}

class  DeadLockTest
{
    public static void main(String[] args) 
    {
        Thread t1= new Thread(new Test(true));
        Thread t2= new Thread(new Test(false));
        t1.start();
        t2.start();

    }
}

/*
經(jīng)典:面試用。

JDK1.5中提供了多線程升級解決方案
將同步synchronized替換成顯示的Lock操作
將Object中的wait,notify,notifyAll,替換了condition對象。
該對象可以通過Lock鎖進(jìn)行獲取

該示例中,實現(xiàn)了本方只喚醒對方的操作。

*/
class Resource
{
    private String name;
    private int count = 1;
    private boolean flag = false;
    
    private Lock lock = new ReentrantLock();
    private Condition condition_pro = lock.newCondition();
    private Condition condition_con = lock.newCondition();

    public void set(String name)throws InterruptedException
    {
        lock.lock();
        try
        {
            while(flag)
            condition_pro.await();
            this.name = name+"--"+count++;
            
            System.out.println(Thread.currentThread().getName()+"...生產(chǎn)者........."+this.name);
            flag = true;
            condition_con.signal();
        }finally
        {
            lock.unlock();//釋放鎖的動作一定要執(zhí)行,放在finally里面
        }       
    }
    public void out()throws InterruptedException
    {
        lock.lock();
        try
        {
            while(!flag)
                condition_con.await();
            System.out.println(Thread.currentThread().getName()+"...消費者..."+this.name);
            flag = false;
            condition_pro.signal();

        }finally
        {
            lock.unlock();
        }
        

    }
}

class Producer implements Runnable
{
    private Resource res;

    Producer(Resource res)
    {
        this.res = res;
    }
    public void run()
    {
        while(true)
        {
            try
            {
                res.set("+商品+");
            }
            catch (InterruptedException e)
            {
            }
            
        }
    }
}
class Consumer implements Runnable
{
    private Resource res;
    Consumer(Resource res)
    {
        this.res = res;
    }
    public void run()
    {
        while(true)
        {
            try
            {
                res.out();
            }
            catch (InterruptedException e)
            {
            }
        }
    }
}


/*
線程間通訊:
其實就是多個線程在操作同一個資源
但是操作的動作不同。
*/

class Res
{
    private String name;
    private String sex;
    private boolean flag = false;
    public synchronized void set(String name,String sex)
    {
        this.name = name;
        this.sex = sex;
    }

    public synchronized void out()
    {
        System.out.println(name+"....."+sex);
    }
}


class Input implements Runnable
{
    private Res r;
    //Object obj = new Object();
    Input(Res r)
    {
        this.r = r;
    }
    public void run()
    {
        int x = 0;
        while(true)
        {
            //synchronized(Input.class)  只要在內(nèi)存中是唯一的對象就行
            synchronized(r)
            {
                if(r.flag)
                    try{r.wait();}catch(Exception e){}
                if(x == 0)
                {
                    r.name = "mike";
                    r.sex = "man";
                }
                else
                {
                    r.name = "麗麗";
                    r.sex = "女";
                }
                x = (x+1)%2;
                r.flag = true;
                r.notify();
            }
        }
    }
}
class Output implements Runnable
{
    private Res r;
    //Object obj = new Object();
    Output(Res r)
    {
        this.r = r;
    }
    public void run()
    {
        while(true)
        {
            //synchronized(Input.class)  只要在內(nèi)存中是唯一的對象就行
            synchronized(r)
            {
                if(!r.flag)
                    try{r.wait();}catch(Exception e){}
                System.out.println(r.name+"..."+r.sex);
                r.flag = false;
                r.notify();
            }
        }
    }
}

class InputOutput 
{
    public static void main(String[] args) 
    {
        Res r = new Res();

        Input in = new Input(r);
        Output op = new Output(r);

        Thread t1 = new Thread(in);
        Thread t2 = new Thread(op);

        t1.start();
        t2.start();
    }
}

/*
wait():
nofity():
notifyAll():
都使用在同步中,因為要對持有監(jiān)視器(鎖)的線程操作。
所以要使用在同步中,因為只有同步才具有鎖。

為什么這些操作線程的方法要定義在Object類中呢?

因為這些方法在操作同步中線程時,都必須要標(biāo)識它們所操作線程持有的鎖,
只有同一個鎖上的被等待線程,可以被同一個鎖上的notify喚醒,
不可以對不同鎖中的線程進(jìn)行喚醒。

也就是說,等待和喚醒必須是同一個鎖,而鎖可以是任意對象,所以
可以被任意對象調(diào)用的方法定義在Object類中。

*/
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容