base64网上实现很多,但是如果是对中文进行编码,有的无法编码,有的编码结果不一致

经过研究,发现base64算法都没有问题,问题出现在汉字的编码上,下面的base64编码稍微做了一些改进,增加了编码判断

所有汉字一律转换成UTF8后再进行base64编码,与网络上通用的base64解码接轨。

以下base64算法使用了开源库uchardet,需要下载uchardet源码编译生成动态库调用

uchardet源码网址:官网地址

/**
* base64编码原理
* 1. 源数据都是8位位宽的数据;
* 2. 相当于分组码,将源数据分为3个一组,每一组共24bits,采用每6位对应一个编码码字,那么3*8bits = 4*6its,将3个数据映射成4个数据,
由于编码的码字都是6位长度,换位10进制就是0-63,总共有64中可能性,这也是base64名字的来历;
* 3. 6bits对应10进制数对应的码字如表;[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/]
* 转解码过程
* 3 * 8 = 4 * 6; 3字节占24位, 4*6=24
* 先将要编码的转成对应的ASCII值
* 如编码: s 1 3
* 对应ASCII值为: 115 49 51
* 对应二进制为: 01110011 00110001 00110011
* 将其6个分组分4组: 011100 110011 000100 110011
* 而计算机是以8bit存储, 所以在每组的高位补两个0如下:
* 00011100 00110011 00000100 00110011对应:28 51 4 51
* 查找base64 转换表 对应 c z E z
*
* 解码
* c z E z
* 对应ASCII值为 99 122 69 122
* 对应表base64_suffix_map的值为 28 51 4 51
* 对应二进制值为 00011100 00110011 00000100 00110011
* 依次去除每组的前两位, 再拼接成3字节
* 即: 01110011 00110001 00110011
* 对应的就是s 1 3
*/
#ifndef __BASE64_H_
#define __BASE64_H_ /********************************************************
Func Name: base64_encode
Date Created: 2018-8-3
Description: base64编码
Input: plaintext_in:源文件
length_in:源文件长度
Output: code_out:生成编码文件
length_out:生成编码文件的长度
Return:
Caution: code_out内存由调用函数释放
*********************************************************/
int base64_encode(const char *plaintext_in, int length_in, char **code_out, int *length_out); /********************************************************
Func Name: base64_decode
Date Created: 2018-8-3
Description: base64解码
Input: code_in;编码后的文件
length_in:编码后的文件长度
Output: plaintext_out:源文件
outlen:源文件长度
Return:
Caution: plaintext_out内存由调用函数释放
*********************************************************/
int base64_decode(char *code_in, int length_in, char **plaintext_out, int *outlen); /********************************************************
Func Name: base64_encode_calculate
Date Created: 2018-8-2
Description: 编码算法
Input: plaintext_in:源文件
length_in:源文件长度
Output: code_out:生成编码文件
length_out:生成编码文件的长度
Return:
Caution: code_out内存由调用函数释放
*********************************************************/
int base64_encode_calculate(const char *plaintext_in, int length_in, char **code_out, int *length_out); /********************************************************
Func Name: base64_decode_calculate
Date Created: 2018-8-3
Description: 解码算法
Input: code_in;编码后的文件
length_in:编码后的文件长度
Output: plaintext_out:源文件
outlen:源文件长度
Return:
Caution: plaintext_out内存由调用函数释放
*********************************************************/
int base64_decode_calculate(char *code_in, int length_in, char **plaintext_out, int *outlen); #endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h> #include "base64.h"
#include "ucharcode.h" #define SRC_CHAR_SIZE 3 //源码3个字节
#define BASE_CHAR_SIZE 4 //编码后4个字节
#define CHAR_SIZE 8 //一个字节有8bits
#define BASE_DATA_SIZE 6 //base编码中6个bits是实际数据 #define DEFAULT_CODE "UTF-8" /********************************************************
Func Name: base64_encode_value
Date Created: 2018-8-2
Description: 获取对应编码的值
Input: value_in:需要编码的字符
Output:
Return:
Caution:
*********************************************************/
char base64_encode_value(char value_in)
{
static const char* encoding = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
if (value_in > ) return '=';
return encoding[(int)value_in];
} /********************************************************
Func Name: base64_decode_value
Date Created: 2018-8-2
Description: 获取对应解码的值
Input: value_in:需要解码的字符
Output:
Return:
Caution:
*********************************************************/
int base64_decode_value(char value_in)
{
static const char decoding[] = {,-,-,-,,,,,,
,,,,,,-,-,-,-,-
,-,-,,,,,,,,
,,,,,,,,,,
,,,,,,,,,-,-
,-,-,-,-,,,,,,
,,,,,,,,,,
,,,,,,,,,,}; static const char decoding_size = sizeof(decoding);
//+ 的ascll值是43
value_in -= ;
if (value_in < || value_in >= decoding_size) return -;
return decoding[(int)value_in];
} /********************************************************
Func Name: base64_encode
Date Created: 2018-8-3
Description: base64编码
Input: plaintext_in:源文件
length_in:源文件长度
Output: code_out:生成编码文件
length_out:生成编码文件的长度
Return:
Caution: code_out内存由调用函数释放
*********************************************************/
int base64_encode(const char *plaintext_in, int length_in, char **code_out, int *length_out)
{
int iRet = ;
char * pcCode = NULL;
char *pcOut = NULL;
//因为utf8一个汉字用3个字节表示,gdk用两个字节表示,所以2倍的长度应该是够用的
int iOutLen = length_in * ;
int iLeftNum = iOutLen;
//参数校验
if (NULL == plaintext_in || == length_in || NULL == code_out || NULL == length_out)
{
return -;
}
//编码格式判断
iRet = getStringCode(plaintext_in, length_in, &pcCode);
if( != iRet)
{
return -;
}
if ( == strcmp(pcCode,DEFAULT_CODE))
{
iRet = base64_encode_calculate(plaintext_in, length_in, code_out, length_out);
return iRet;
}
//如果不是UTF-8编码 需要转码
pcOut = (char *)malloc(iOutLen);
if (NULL == pcOut)
{
return -;
}
memset(pcOut, , iOutLen);
iRet = transcodeToUTF8((char *)plaintext_in, length_in, pcOut, &iLeftNum, pcCode);
if ( != iRet)
{
//释放资源
if (pcOut)
{
free(pcOut);
pcOut = NULL;
}
return -;
} //释放编码资源
if (pcCode)
{
free(pcCode);
pcCode = NULL;
}
iRet = base64_encode_calculate(pcOut, iOutLen - iLeftNum, code_out, length_out); //释放资源
if (pcOut)
{
free(pcOut);
pcOut = NULL;
} return iRet; } /********************************************************
Func Name: base64_encode_calculate
Date Created: 2018-8-2
Description: 编码算法
Input: plaintext_in:源文件
length_in:源文件长度
Output: code_out:生成编码文件
length_out:生成编码文件的长度
Return:
Caution: code_out内存由调用函数释放
*********************************************************/
int base64_encode_calculate(const char *plaintext_in, int length_in, char **code_out, int *length_out)
{
int iPadLen = ; //需要补齐的字节数
int iBaseLen = ; //base64编码后的字节数
int i = ;
char *pcOut = NULL;
char gPadChar[BASE_CHAR_SIZE] = {};
char * pcOutIndex = NULL; if (NULL == plaintext_in || == length_in || NULL == code_out || NULL == length_out)
{
return -;
} if ( != length_in % SRC_CHAR_SIZE)
{
//3 - length_in%3 源码需要添加的字节数
iPadLen = SRC_CHAR_SIZE - length_in % SRC_CHAR_SIZE;
}
//计算base编码后实际长度 +1 最后一个字符是'/0'
iBaseLen = (length_in + iPadLen)* CHAR_SIZE / BASE_DATA_SIZE + ; pcOut = (char *)malloc(sizeof(char) * iBaseLen);
if (NULL == pcOut)
{
return -;
}
memset(pcOut, , sizeof(char) * iBaseLen);
pcOutIndex = pcOut; for (i = ; i < length_in; i += SRC_CHAR_SIZE)
{
if (i == (length_in + iPadLen -) && != iPadLen)
{
if ( == iPadLen)
{
//末尾实际上有两个字节的数据,将这两个字节的数据进行编码 //第一个字节处理
gPadChar[] = base64_encode_value(*(plaintext_in+i) >> & 0x3f); //第二个字节处理
gPadChar[] = base64_encode_value((*(plaintext_in+i) << >> & 0x30) + (*(plaintext_in+i+) >> & 0xf)); //第二个字节最后4bits处理,不足的补0
gPadChar[] = base64_encode_value((*(plaintext_in+i+) << >> & 0x3c)); //没有字节的以'='代替 因为base编码只有6bit真实数据,所以不会和源数据中的"="重复
gPadChar[] = '='; }else if ( == iPadLen)
{
//末尾实际上有一个字节的数据,将这一个字节的数据进行编码
//第一个字节处理
gPadChar[] = base64_encode_value(*(plaintext_in+i) >> & 0x3f); //第一个字节最后2bits处理
gPadChar[] = base64_encode_value((*(plaintext_in+i) << >> & 0x30)); gPadChar[] = '=';
gPadChar[] = '=';
} }else
{
//第一个字节处理 0x3f前两位清零
//取第一个字节的前6bits
gPadChar[] =base64_encode_value(*(plaintext_in+i) >> & 0x3f); //第二个字节处理
//*(pcIndex+i) << 6 >> 2 & 0x30 取第一个字节的后2bits 无效数据清零
//*(pcIndex+i+1) >> 4 & 0xf 取第二个字节的前4bits 无效数据清零
gPadChar[] = base64_encode_value((*(plaintext_in+i) << >> & 0x30) + (*(plaintext_in+i+) >> & 0xf)); //第二个字节和第三个字节处理
//*(pcIndex+i+1) << 4 >> 2 & 0x3c 取第二个字节的后4bits数据 无效数据清零
//(*(pcIndex+i+2) >> 6 & 0x3 取第三个字节的前2bits数据 无效数据清零
gPadChar[] = base64_encode_value((*(plaintext_in+i+) << >> & 0x3c) + (*(plaintext_in+i+) >> & 0x3)); //第三个字节处理
//*(pcIndex+i+2) & 0x3f 清除第三个字节的前2bits数据
gPadChar[] = base64_encode_value(*(plaintext_in+i+) & 0x3f);
} //并非字符串操作,不能使用strcat
memcpy(pcOutIndex, gPadChar, BASE_CHAR_SIZE);
pcOutIndex += BASE_CHAR_SIZE; memset(gPadChar, , BASE_CHAR_SIZE);
} pcOut[iBaseLen-] = ;
*length_out = iBaseLen;
*code_out = pcOut; return ;
} /********************************************************
Func Name: base64_decode
Date Created: 2018-8-3
Description: base64解码
Input: code_in;编码后的文件
length_in:编码后的文件长度
Output: plaintext_out:源文件
outlen:源文件长度
Return:
Caution: plaintext_out内存由调用函数释放
*********************************************************/
int base64_decode(char *code_in, int length_in, char **plaintext_out, int *outlen)
{
int iRet = base64_decode_calculate(code_in, length_in, plaintext_out, outlen);
return iRet;
} /********************************************************
Func Name: base64_decode_calculate
Date Created: 2018-8-3
Description: 解码算法
Input: code_in;编码后的文件
length_in:编码后的文件长度
Output: plaintext_out:源文件
outlen:源文件长度
Return:
Caution: plaintext_out内存由调用函数释放
*********************************************************/
int base64_decode_calculate(char *code_in, int length_in, char **plaintext_out, int *outlen)
{
int i = , j = ;
int iPadNum = ;
char *pcSrc = code_in;
char * pcIndex = NULL;
int iSrcLen = ;
char *pcOut = NULL; if (NULL == code_in || NULL == plaintext_out || NULL == outlen)
{
return -;
} while()
{
pcIndex = strchr(pcSrc, '=');
if (NULL == pcIndex)
{
break;
}
iPadNum++;
pcIndex += ;
pcSrc = pcIndex; }
//计算源文件的字符个数
iSrcLen = length_in/* - iPadNum; //末尾增加\0
pcOut = (char *)malloc(sizeof(char)*iSrcLen + );
if (NULL == pcOut)
{
return -;
}
memset(pcOut, , sizeof(char)*iSrcLen + ); for (i = , j = ; i < length_in; i += )
{
if ((i == length_in-) && iPadNum > )
{
if ( == iPadNum)
{
//实际上有两个字符 只能用3个base字符表示 //字符1
pcOut[j] = (base64_decode_value(code_in[i]) << ) + (base64_decode_value(code_in[i+]) << >> & 0x3);
//字符2
pcOut[j+] = (base64_decode_value(code_in[i+]) << ) + (base64_decode_value(code_in[i+]) << >> & 0xf);
j += ;
}else if ( == iPadNum)
{
//实际上有1个字符数据 只能用2个base字符表示
pcOut[j] = (base64_decode_value(code_in[i])<<) + (base64_decode_value(code_in[i+]) << >> &0x3);
j ++;
}
}else
{
//字符1
pcOut[j] = (base64_decode_value(code_in[i])<<) + (base64_decode_value(code_in[i+]) << >> &0x3);
//字符2
pcOut[j+] = (base64_decode_value(code_in[i+]) << ) + (base64_decode_value(code_in[i+]) << >> & 0xf);
//字符3
pcOut[j+] = (base64_decode_value(code_in[i+]) << ) + (base64_decode_value(code_in[i+]) & 0x3f);
j += ;
}
} pcOut[iSrcLen] = '\0';
*plaintext_out = pcOut;
*outlen = iSrcLen; return ;
}
#ifndef __UNCHARCODE_H_
#define __UNCHARCODE_H_ /********************************************************
Func Name: getStringCode
Date Created: 2018-8-3
Description: 获取字符串编码
Input: pcSrc:源编码数据
iLenIn:源编码长度
pcCode:结果存放内存地址
Output:
Return: error code
Caution: pcDest内存需要由调用函数释放
*********************************************************/
int getStringCode(const char *pcSrc, int iLenIn, char **pcCode); /********************************************************
Func Name: transcodeToUTF8
Date Created: 2018-8-3
Description: 转码UTF8
Input: pcSrc:源编码数据
lenIn:源编码长度
pcDest:结果存放内存地址(INOUT)
lenOut:剩余内存单位个数(INOUT)
pcCodeType:源编码类型
Output:
Return: error code
Caution: pcDest内存需要由调用函数分配
*********************************************************/
int transcodeToUTF8(char *pcSrc, int lenIn, char *pcDest, int *lenOut,const char *pcCodeType); /********************************************************
Func Name: transcodeToGBK
Date Created: 2018-8-3
Description: 转码GBK
Input: pcSrc:源编码数据
lenIn:源编码长度
pcDest:结果存放内存地址(INOUT)
lenOut:剩余内存单位个数(INOUT)
pcCodeType:源编码类型
Output:
Return: error code
Caution: pcDest内存需要由调用函数分配
*********************************************************/
int transcodeToGBK(char *pcSrc, int lenIn, char *pcDest, int *lenOut,const char *pcCodeType); #endif
#include <stdlib.h>
#include <string.h>
#include <iconv.h> #include "ucharcode.h"
#include "uchardet.h" /********************************************************
Func Name: transcodeToUTF8
Date Created: 2018-8-3
Description: 转码UTF8
Input: pcSrc:源编码数据
lenIn:源编码长度
pcDest:结果存放内存地址(INOUT)
lenOut:剩余内存单位个数(INOUT)
pcCodeType:源编码类型
Output:
Return: error code
Caution: pcDest内存需要由调用函数分配
*********************************************************/
int fromcodeToCode(char *pcSrc, int lenIn, char *pcDest, int *lenOut, const char *pcFromCode, const char *pcToCode)
{
int iRet = ; //由于iconv()函数会修改指针,所以要保存源指针
char *pcStart = pcSrc;
char *pcOut = pcDest; iconv_t cd = (iconv_t)-;
size_t inbytesleft = (size_t)lenIn; if (NULL == pcSrc || >= lenIn || NULL == pcDest || NULL == lenOut || NULL == pcFromCode || NULL == pcToCode)
{
return -;
} cd = iconv_open(pcToCode, pcFromCode);
if ((iconv_t)- == cd)
{
return -;
} /*
*@param cd iconv_open()产生的句柄
*@param pcStart 需要转换的字符串
*@param inbytesleft 存放还有多少字符没有转换
*@param pcOut 存放转换后的字符串
*@param outlen 存放转换后,pcOut剩余的空间
*/
iRet = iconv(cd, &pcStart, &inbytesleft, &pcOut, (size_t *)lenOut);
if (iRet < )
{
return -;
} iconv_close(cd); return iRet;
} /********************************************************
Func Name: transcodeToUTF8
Date Created: 2018-8-3
Description: 转码UTF8
Input: pcSrc:源编码数据
lenIn:源编码长度
pcDest:结果存放内存地址(INOUT)
lenOut:剩余内存单位个数(INOUT)
pcCodeType:源编码类型
Output:
Return: error code
Caution: pcDest内存需要由调用函数分配
*********************************************************/
int transcodeToUTF8(char *pcSrc, int lenIn, char *pcDest, int *lenOut,const char *pcCodeType)
{
int iRet = ; const char * targetCode = "UTF8";
if (NULL == pcSrc || >= lenIn || NULL == pcDest || NULL == lenOut || NULL == pcCodeType)
{
return -;
} iRet = fromcodeToCode(pcSrc, lenIn, pcDest, lenOut, pcCodeType, targetCode); return iRet;
} /********************************************************
Func Name: transcodeToGBK
Date Created: 2018-8-3
Description: 转码GBK
Input: pcSrc:源编码数据
lenIn:源编码长度
pcDest:结果存放内存地址(INOUT)
lenOut:剩余内存单位个数(INOUT)
pcCodeType:源编码类型
Output:
Return: error code
Caution: pcDest内存需要由调用函数分配
*********************************************************/
int transcodeToGBK(char *pcSrc, int lenIn, char *pcDest, int *lenOut, char *pcCodeType)
{
int iRet = ; const char * targetCode = "GBK";
if (NULL == pcSrc || >= lenIn || NULL == pcDest || NULL == lenOut || NULL == pcCodeType)
{
return -;
} iRet = fromcodeToCode(pcSrc, lenIn, pcDest, lenOut, pcCodeType, targetCode); return iRet;
} /********************************************************
Func Name: getStringCode
Date Created: 2018-8-3
Description: 获取字符串编码
Input: pcSrc:源编码数据
iLenIn:源编码长度
pcCode:结果存放内存地址
Output:
Return: error code
Caution: pcDest内存需要由调用函数释放
*********************************************************/
int getStringCode(const char *pcSrc, int iLenIn, char **pcCode)
{
uchardet_t ud;
int iErrorCode = ;
char *pcBuf = NULL;
const char *pcDest = NULL; if (NULL == pcSrc || == iLenIn || NULL == pcCode)
{
return -;
} ud = uchardet_new(); //如果样本字符不够,那么有可能导致分析失败
iErrorCode = uchardet_handle_data(ud, pcSrc, iLenIn);
if ( != iErrorCode)
{
return -;
} uchardet_data_end(ud); pcDest = uchardet_get_charset(ud); //+1 多留一个字符'\0'
pcBuf = (char *)malloc(strlen(pcDest)+);
if (NULL == pcBuf)
{
return -;
}
memset(pcBuf, , strlen(pcDest)+); strcpy(pcBuf,pcDest); *pcCode = pcBuf; uchardet_delete(ud); return ;
}
#include <iostream>
#include <cstring> #include "base64.h" using namespace std; /* 测试小程序 */ void test()
{
int len = ;
int iRet= ;
char *pcOut = NULL; const char* s = "我是中国人";
char * pcBuf = NULL;
int lastLen = ; //base64编码
iRet = base64_encode((char *)s, strlen(s), &pcOut, &len);
if ( != iRet)
{
cout << "base64_encode() error ." << endl;
}
cout << "result = " << pcOut << endl; //base64解码
iRet = base64_decode(pcOut, len, &pcBuf, &lastLen);
if ( != iRet)
{
cout << "base64_decode() error ." << endl;
}
cout << "end len = " << lastLen << " result = " << pcBuf << endl;
if (pcOut)
{
free(pcOut);
pcOut = NULL;
}
if (pcBuf)
{
free(pcBuf);
pcBuf = NULL;
}
} int main()
{
test();
getchar();
return ;
}

Linux共享库 base64库的更多相关文章

  1. linux共享库

    linux共享库 linux中共享库一般以.so.x.y.z 命名,其中x,y,z分别为主版本号.次版本号.发布版本号.同一个库,主版本号不同则相互不兼容:主版本相同,次版本号高的库比次版本号低的库有 ...

  2. Linux共享库两种加载方式简述

      Linux共享库两种加载方式简述  动态库技术通常能减少程序的大小,节省空间,提高效率,具有很高的灵活性,对于升级软件版本也更加容易.与静态库不同,动态库里面的函数不是执行程序本身 的一部分,而是 ...

  3. linux环境 :Linux 共享库LIBRARY_PATH, LD_LIBRARY_PATH 与ld.so.conf

    参考: 1. Linux 共享库:LD_LIBRARY_PATH 与ld.so.conf Linux环境变量名,该环境变量主要用于指定查找共享库(动态链接库)时除了默认路径之外的其他路径.(该路径在默 ...

  4. Linux共享库、静态库、动态库详解

    1. 介绍 使用GNU的工具我们如何在Linux下创建自己的程序函数库?一个“程序函数库”简单的说就是一个文件包含了一些编译好的代码和数据,这些编译好的代码和数据可以在事后供其他的程序使用.程序函数库 ...

  5. linux下的静态库和共享库

    转载&&增加:      我们在编写一个C语言程序的时候,经常会遇到好多重复或常用的部分,如果每次都重新编写固然是可以的,不过那样会大大降低工作效率,并且影响代码的可读性,更不利于后期 ...

  6. linux共享库加载

    参考自: <<程序员的自我修养--链接.装载与库>> 第八章 Linux共享库的组织 以下截取部分内容 (这本书比较好的讲解了从程序的链接,装载,到运行) 共享库的兼容性 li ...

  7. linux共享库的版本控制

    前几天看到一篇介绍linux共享库版本控制及使用的文章,觉得不错,这里就与大家分享一下. 1. Linux约定 经常看到Linux中,共享库的名字后面跟了一串数字,比如:libperl.so.5.18 ...

  8. Linux共享库简单总结

    库 静态库 编译的二进制会重新包含一份静态库的副本 共享库 编译 gcc -shared -o file.c -fPIC 链接 ld ld-linux.so.2 可执行程序–>动态依赖表 流程: ...

  9. Linux中的动态库和静态库(.a/.la/.so/.o)

    Linux中的动态库和静态库(.a/.la/.so/.o) Linux中的动态库和静态库(.a/.la/.so/.o) C/C++程序编译的过程 .o文件(目标文件) 创建atoi.o 使用atoi. ...

随机推荐

  1. 开始学习使用 Semantic UI

    最近在找一个功能比较丰富的前端框架,之前一直使用的Bootstrap,感觉组件还是不够丰富,很多东西都需要不少自定义.于是就发现了 Semantic UI. 不过感觉网上相关的中文资料好少,官方网站( ...

  2. NSString和NSMutablestring,copy和strong(转载)

    1.http://www.cocoachina.com/ios/20150512/11805.html 2.http://blog.csdn.net/winzlee/article/details/5 ...

  3. 在Android Studio 和 Eclipse 的 git 插件操作 "代码提交"以及"代码冲突"

    面向对象:曾经使用过SVN的同学. (因为Git 它 可以说是双重的SVN (本地一个服务器,远程一个服务器)),提交代码要有两次步骤,先提交到本地服务器,再把本地服务器在提交到远程服务器. 所以连S ...

  4. eclipse自动切换到debug视图

    原文出自:http://blog.csdn.net/yizhizouxiaqu/article/details/7594502 当弹出"Confir Perspective Switch&q ...

  5. Atitit 软件项目系统托盘图标解决方案

    Atitit 软件项目系统托盘图标解决方案 1.1. Nodejs   node-webkit还实现了本地化的API,例如菜单栏,系统的托盘图标支持1 1.2. Java c# qt c++1 1.3 ...

  6. 【Unity】11.1 角色控制器 (Character Controller)

    分类:Unity.C#.VS2015 创建日期:2016-05-02 一.简介 角色控制器(Character Controller)主要用于对第三人称或第一人称游戏主角的控制.如果要创建类人角色,可 ...

  7. error_page 改变状态码为新的状态码,并显示指定内容

    server { listen 80; server_name www.espressos.com; location / { root /data0/www/bbs; index index.htm ...

  8. Java 编程中关于异常处理的 10 个最佳实践

    异常处理是Java 开发中的一个重要部分.它是关乎每个应用的一个非功能性需求,是为了处理任何错误状况,比如资源不可访问,非法输入,空输入等等.Java提供了几个异常处理特性,以try,catch 和 ...

  9. iOS开发如何学习前端(1)

    iOS开发如何学习前端(1) 我为何学前端?因为无聊. 概念 前端大概三大块. HTML CSS JavaScript 基本上每个概念在iOS中都有对应的.HTML请想象成只能拉Autolayout或 ...

  10. Java套接字Socket编程--TCP参数

    在Java的Socket中,主要包含了以下可设置的TCP参数. 属性 说明 默认值 SO_TIMEOUT 对ServerSocket来说表示等待连接的最长空等待时间; 对Socket来说表示读数据最长 ...