Java傳遞音頻給PC端C#程序(1)

需求

把Android手機(jī)的mp3文件以TCP的傳輸方式傳遞到Win10的C#程序上,并且附帶歌名等信息赌厅。
PC端的要求是傳遞一個(gè)序列化后的文件過(guò)去,里面包含了文件本體和文件名等信息轿塔。
該序列化(C#這里的序列化好像和Java里面相差甚大疤卦浮!起初我是一頭霧水的)后的文件格式如下:

QQ圖片20170317130027.png

( ⊙o⊙ )? 什么鬼勾缭,沒(méi)辦法硬著頭皮試揍障,起初根本不知道這是什么碼,因?yàn)樵贏ndroid里俩由,傳遞文件最底層的就是字節(jié)流亚兄,那這個(gè)又是什么編碼呢。

嘗試

方式有很多種采驻,比如把所有信息轉(zhuǎn)成字節(jié)傳遞過(guò)去审胚,但是告知對(duì)方在哪里是什么,這種很麻煩礼旅;把文件轉(zhuǎn)成byte[]后放入一個(gè)類(lèi)中膳叨,該類(lèi)攜帶歌曲信息以byte[]發(fā)送過(guò)去。
嘗試了幾種方法:

1痘系、 第一次(失敺谱臁)

ObjectOutputSteam object = new ObjectOutputStream(socket.getOutputStream());

通過(guò)對(duì)象流發(fā)送,發(fā)送過(guò)去后直接亂碼了,不用說(shuō)龄坪,肯定是不能通過(guò)這樣的方式發(fā)送了昭雌,因?yàn)閷?duì)象流是JVM之間的一種傳遞方式,把對(duì)象以這種方式傳遞明顯行不通健田。

2烛卧、 第二次(失敗)

直接利用文件流把文件轉(zhuǎn)成byte[]然后傳遞過(guò)去妓局,但是這種傳遞沒(méi)有辦法傳遞歌曲信息总放,嘗試用類(lèi)來(lái)包裹

byte[] musicBytes = getBytes(filePath);//歌曲文件的字節(jié)數(shù)組
SimpleMusicEntity simpleMusicEntity = new SimpleMusicEntity();
simpleMusicEntity.setMusicBytes(musicBytes);
simpleMusicEntity.setTitle(title);
    /**
     * 獲得指定文件的byte數(shù)組
     */
    public static byte[] getBytes(String filePath) {
        byte[] buffer = null;
        try {
            File file = new File(filePath);
            FileInputStream fis = new FileInputStream(file);
            ByteArrayOutputStream bos = new ByteArrayOutputStream(1024);
            byte[] b = new byte[1024];
            int n;
            while ((n = fis.read(b)) != -1) {
                bos.write(b, 0, n);
            }
            fis.close();
            bos.close();
            buffer = bos.toByteArray();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return buffer;
    }

so,問(wèn)題來(lái)了好爬,我得到了一個(gè)類(lèi)SimpleMusicEntity局雄,里面富含了歌曲的所有信息(名稱(chēng)、ext存炮、文件字節(jié))炬搭,怎么傳呢。
用Gson轉(zhuǎn)對(duì)象為Json傳遞過(guò)去穆桂,成功了宫盔!就這么的,我測(cè)試了傳遞一曲“滴滴滴.mp3”成功了充尉,對(duì)方從其中拿到byte[]數(shù)組轉(zhuǎn)文件也能播放成功。繼續(xù)測(cè)試衣形,傳一首歌曲驼侠,直接OOM!錯(cuò)誤大概是消耗了幾十兆的空間導(dǎo)致App直接crash谆吴。

為什么呢倒源,顯而易見(jiàn),因?yàn)樽址L(zhǎng)了句狼!你把一個(gè)歌曲轉(zhuǎn)換成byte[]然后再轉(zhuǎn)換成String笋熬,你知道這個(gè)String.length()有多長(zhǎng)么,不說(shuō)了高興太早腻菇。

3胳螟、第三次

找了半天終于知道有這么一個(gè)東西“Base64”!
目前的做法是File轉(zhuǎn)byte[]筹吐,byte[]通過(guò)轉(zhuǎn)為Base64的字符串糖耸,這樣得到的文件大小比原文件大1.2倍左右(拿首歌曲測(cè)試)

        byte[] musicBytes = getBytes(filePath);//歌曲文件的字節(jié)數(shù)組
        String str = new String(Base64.encode(musicBytes, Base64.NO_WRAP ));
        SimpleMusicEntity2 simpleMusicEntity2 = new SimpleMusicEntity2();
        simpleMusicEntity2.setMusicBytes(str);
        simpleMusicEntity2.setTitle(title);
        String string =simpleMusicEntity2.toString;
public class SimpleMusicEntity2{

    private String title;
    private String musicBytes;

    //構(gòu)造一個(gè)json字符串
    @Override
    public String toString() {
        return "{"
                + "\"title\":"
                + "\"" + title + '\"'
                + ","
                + "\"musicBytes\":"
                + "\"" + musicBytes + '\"' +
                '}'+
                "\r\n"
                ;
    }
}

Base64簡(jiǎn)單說(shuō)一下

上面第二行“Base64.NO_WRAP”
為什么要用這個(gè),因?yàn)槿绻肂ase64.DEFAULT的話丘薛,我們的string里會(huì)自動(dòng)添加換行符“\n”

flag常量

Base64.CRLF 這個(gè)參數(shù)意思是Win風(fēng)格的換行符嘉竟,意思就是使用CR LF這一對(duì)作為一行的結(jié)尾而不是Unix風(fēng)格的LF
Base64.DEFAULT 這個(gè)參數(shù)是默認(rèn),使用默認(rèn)的方法來(lái)加密
Base64.NO_PADDING 這個(gè)參數(shù)是略去加密字符串最后的”=”
Base64.NO_WRAP 這個(gè)參數(shù)意思是略去所有的換行符(設(shè)置后CRLF就沒(méi)用了)
Base64.URL_SAFE 這個(gè)參數(shù)意思是加密時(shí)不使用對(duì)URL和文件名有特殊意義的字符來(lái)作為加密字符,具體就是以-和_取代+和/
//習(xí)慣上使用Base64.NO_WRAP舍扰,使用什么方式編碼就需要使用什么方式解碼倦蚪。

Base64Api

//將字節(jié)數(shù)組編碼,返回為String
Base64.encodeToString(byte[] bs,int flag);
//將字節(jié)數(shù)組編碼边苹,返回字節(jié)數(shù)組
Base64.encode(byte[] bs,int flag);
//將字節(jié)數(shù)組按指定位置部分編碼陵且,返回字符串
Base64.encodeToString(byte[] bs,int offset,int lenth);
//將字節(jié)數(shù)組按指定位置部分編碼,返回字節(jié)數(shù)組
Base64.encode(byte[] bs,int offset,int lenth);
//將編碼后的字符串解碼返回字節(jié)數(shù)組
Base64.decode(String str,int flag);
//將編碼后的字節(jié)數(shù)組解碼返回字節(jié)數(shù)組
Base64.decode(byte[],int flag);
//將編碼后的字節(jié)數(shù)組按指定位置部分解碼勾给,返回字節(jié)數(shù)組
Base64.decode(byte[] bs,int offset,int len);

最后

發(fā)送方式滩报,下面兩種方式都行:

        byte[] bytes = string.getBytes();
        //byte[] enter = "\r\n".getBytes();//這個(gè)換行符必須寫(xiě)在字符串末端,不能單獨(dú)發(fā)送換行符
        DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream()));
        dos.write(bytes);
        //dos.write(enter);
        dos.flush();
        dos.close();
        BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
        bufferedWriter.write(string);
        bufferedWriter.flush();
        bufferedWriter.close();

終于PC端的C#程序能接收到文件信息播急,也能正確播放了脓钾,并且也有歌曲名字。

如果文件較大桩警,可以先zip壓縮可训。如果還是較大,可以分段傳輸捶枢。

缺點(diǎn)

這種傳遞文件的做法不推薦握截,因?yàn)閭鬟f10M以上的文件極有可能OOM,因?yàn)镴ava虛擬機(jī)頂不住烂叔。

改進(jìn)

請(qǐng)看第二篇文章Java傳遞音頻給PC端C#程序(2)

這只是功能demo而已谨胞,其實(shí)Android還要考慮很多,比如ip是變化的蒜鸡,我怎么獲取對(duì)應(yīng)設(shè)備的ip胯努,然后建立TCP連接等等。

喝水不忘挖井人

參考文獻(xiàn):
Android編碼解碼及其原理
文件與base64二進(jìn)制轉(zhuǎn)換
圖片與Base64相互轉(zhuǎn)換,c#與java通用
Byte[]和BASE64之間的轉(zhuǎn)換
對(duì)文件進(jìn)行base64編碼成字符串進(jìn)行保存或傳輸

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末逢防,一起剝皮案震驚了整個(gè)濱河市叶沛,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌忘朝,老刑警劉巖灰署,帶你破解...
    沈念sama閱讀 218,858評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異局嘁,居然都是意外死亡溉箕,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)悦昵,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)约巷,“玉大人,你說(shuō)我怎么就攤上這事旱捧《览桑” “怎么了踩麦?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,282評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)氓癌。 經(jīng)常有香客問(wèn)我谓谦,道長(zhǎng),這世上最難降的妖魔是什么贪婉? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,842評(píng)論 1 295
  • 正文 為了忘掉前任反粥,我火速辦了婚禮,結(jié)果婚禮上疲迂,老公的妹妹穿的比我還像新娘才顿。我一直安慰自己,他們只是感情好尤蒿,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,857評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布郑气。 她就那樣靜靜地躺著,像睡著了一般腰池。 火紅的嫁衣襯著肌膚如雪尾组。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,679評(píng)論 1 305
  • 那天示弓,我揣著相機(jī)與錄音讳侨,去河邊找鬼。 笑死奏属,一個(gè)胖子當(dāng)著我的面吹牛跨跨,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播囱皿,決...
    沈念sama閱讀 40,406評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼勇婴,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了铆帽?” 一聲冷哼從身側(cè)響起咆耿,我...
    開(kāi)封第一講書(shū)人閱讀 39,311評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤德谅,失蹤者是張志新(化名)和其女友劉穎爹橱,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體窄做,經(jīng)...
    沈念sama閱讀 45,767評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡愧驱,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了椭盏。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片组砚。...
    茶點(diǎn)故事閱讀 40,090評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖掏颊,靈堂內(nèi)的尸體忽然破棺而出糟红,到底是詐尸還是另有隱情艾帐,我是刑警寧澤,帶...
    沈念sama閱讀 35,785評(píng)論 5 346
  • 正文 年R本政府宣布盆偿,位于F島的核電站柒爸,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏事扭。R本人自食惡果不足惜捎稚,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,420評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望求橄。 院中可真熱鬧今野,春花似錦、人聲如沸罐农。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,988評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)啃匿。三九已至蛔外,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間溯乒,已是汗流浹背夹厌。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,101評(píng)論 1 271
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留裆悄,地道東北人矛纹。 一個(gè)月前我還...
    沈念sama閱讀 48,298評(píng)論 3 372
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像光稼,于是被迫代替她去往敵國(guó)和親或南。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,033評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語(yǔ)法艾君,類(lèi)相關(guān)的語(yǔ)法采够,內(nèi)部類(lèi)的語(yǔ)法,繼承相關(guān)的語(yǔ)法冰垄,異常的語(yǔ)法蹬癌,線程的語(yǔ)...
    子非魚(yú)_t_閱讀 31,639評(píng)論 18 399
  • 編碼問(wèn)題一直困擾著開(kāi)發(fā)人員,尤其在 Java 中更加明顯虹茶,因?yàn)?Java 是跨平臺(tái)語(yǔ)言逝薪,不同平臺(tái)之間編碼之間的切換...
    x360閱讀 2,480評(píng)論 1 20
  • tags:io categories:總結(jié) date: 2017-03-28 22:49:50 不僅僅在JAVA領(lǐng)...
    行徑行閱讀 2,178評(píng)論 0 3
  • 我希望,將來(lái)我結(jié)婚了蝴罪,是因?yàn)閻?ài)情董济,而不是因?yàn)闂l件合適或?yàn)榱朔毖芎蟠T谖铱磥?lái)要门,感情真的比物質(zhì)重要很多虏肾,感情是點(diǎn)滴的...
    文藝小呆閱讀 267評(píng)論 0 0
  • 28/100 #100天堅(jiān)持一件事# 星期三 雨 早起6:00 早餐:小米紅棗粥 今日背誦經(jīng)文: 弟兄們廓啊,在心...
    zuimeideni閱讀 366評(píng)論 0 0