问题:在用Java程序进行读写含中文的txt文件时,经常会出现读出或写入的内容会出现乱码。原因其实很简单,就是系统的编码和程序的编码采用了不同的编码格式。通常,假如自己不修改的话,windows自身采用的编码格式是gbk(而gbk和gb2312基本上是一样的编码方式),而IDE中Encode不修改的话,默认是utf-8的编码,这就是为什么会出现乱码的原因。当在OS下手工创建并写入的txt文件(gbk),用程序直接去读(utf-8),就会乱码。为了避免可能的中文乱码问题,最好在文件写入和读出的时候显式指定编码格式。
1、写文件:
public static void writeFile(String fileName, String fileContent)
{
try
{
File f = new File(fileName);
if (!f.exists())
{
f.createNewFile();
}
OutputStreamWriter write = new OutputStreamWriter(new FileOutputStream(f),"gbk");
BufferedWriter writer=new BufferedWriter(write);
writer.write(fileContent);
writer.close();
} catch (Exception e)
{
e.printStackTrace();
}
}
public static void writeFile(String fileName, String fileContent)
{
try
2、读文件:
public static String readFile(String fileName)
{
String fileContent = "";
try
{
File f = new File(fileName);
if(f.isFile()&&f.exists())
{
InputStreamReader read = new InputStreamReader(new FileInputStream(f),"gbk");
BufferedReader reader=new BufferedReader(read);
String line;
while ((line = reader.readLine()) != null)
{
fileContent += line;
}
read.close();
}
} catch (Exception e)
{
e.printStackTrace();
}
return fileContent;
}
public static String readFile(String fileName)
{
String fileContent = "";
try
{
File f = new File(fileName);
if(f.isFile()&&f.exists())
{
InputStreamReader read = new InputStreamReader(new FileInputStream(f),"gbk");
BufferedReader reader=new BufferedReader(read);
String line;
while ((line = reader.readLine()) != null)
{
fileContent += line;
}
read.close();
}
} catch (Exception e)
{
e.printStackTrace();
}
return fileContent;
}
在self.view上添加scrollview 能正常滚动,,但再次添加其他的view的时候,就不能正常滚动了。。必须用下面的一个方法。才行。。。。。很好用。的
-(void)viewDidLayoutSubviews{
[superviewDidLayoutSubviews];
self.myScrollView.frame = CGRectMake(0, 0, kScreenWidth, kScreenHeight-44);
self.myScrollView.contentSize = CGSizeMake(kScreenWidth, kMyScrollViewHeight);
}
最近在做一项工作,将基于cocos2d-iphone游戏转换为跨平台版本。
以下为OC代码:
[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:@"game_ui.plist"]; [[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:@"game_effect.plist"];
以下为Lua代码(我们的UI采用Lua编码):
display.addSpriteFramesWithFile('game_ui.plist')
display.addSpriteFramesWithFile('game_effect.plist')
运行时,却发现了在OC版本中没有出现的异常“CCSprite is not using the same texture id”
跟踪该png文件,却发现health_bar.png文件同时存在于这两个plist。
这时候就产生疑问了,OC和C++版本的资源文件都是一样的。为什么cocos2d-x就会报异常呢?
好在cocos2d是开源的,所以开始研究addSpriteFramesWithFile的实现细节。
cocos2d-iphone
-(void) addSpriteFramesWithFile:(NSString*)plist
{
NSAssert(plist, @"plist filename should not be nil");
if( ! [_loadedFilenames member:plist] ) {
NSString *path = [[CCFileUtils sharedFileUtils] fullPathForFilename:plist];
NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:path];
NSString *texturePath = nil;
NSDictionary *metadataDict = [dict objectForKey:@"metadata"];
if( metadataDict )
// try to read texture file name from meta data
texturePath = [metadataDict objectForKey:@"textureFileName"];
if( texturePath )
{
// build texture path relative to plist file
NSString *textureBase = [plist stringByDeletingLastPathComponent];
texturePath = [textureBase stringByAppendingPathComponent:texturePath];
} else {
// build texture path by replacing file extension
texturePath = [plist stringByDeletingPathExtension];
texturePath = [texturePath stringByAppendingPathExtension:@"png"];
CCLOG(@"cocos2d: CCSpriteFrameCache: Trying to use file '%@' as texture", texturePath);
}
[self addSpriteFramesWithDictionary:dict textureFilename:texturePath];
[_loadedFilenames addObject:plist];
}
else
CCLOGINFO(@"cocos2d: CCSpriteFrameCache: file already loaded: %@", plist);
}
cocos2d-x
void CCSpriteFrameCache::addSpriteFramesWithDictionary(CCDictionary* dictionary, CCTexture2D *pobTexture)
{
/*
Supported Zwoptex Formats:
ZWTCoordinatesFormatOptionXMLLegacy = 0, // Flash Version
ZWTCoordinatesFormatOptionXML1_0 = 1, // Desktop Version 0.0 - 0.4b
ZWTCoordinatesFormatOptionXML1_1 = 2, // Desktop Version 1.0.0 - 1.0.1
ZWTCoordinatesFormatOptionXML1_2 = 3, // Desktop Version 1.0.2+
*/
CCDictionary *metadataDict = (CCDictionary*)dictionary->objectForKey("metadata");
CCDictionary *framesDict = (CCDictionary*)dictionary->objectForKey("frames");
int format = 0;
// get the format
if(metadataDict != NULL)
{
format = metadataDict->valueForKey("format")->intValue();
}
// check the format
CCAssert(format >=0 && format <= 3, "format is not supported for CCSpriteFrameCache addSpriteFramesWithDictionary:textureFilename:");
CCDictElement* pElement = NULL;
CCDICT_FOREACH(framesDict, pElement)
{
CCDictionary* frameDict = (CCDictionary*)pElement->getObject();
std::string spriteFrameName = pElement->getStrKey();
CCSpriteFrame* spriteFrame = (CCSpriteFrame*)m_pSpriteFrames->objectForKey(spriteFrameName);
if (spriteFrame)
{
continue;
}
if(format == 0)
{
float x = frameDict->valueForKey("x")->floatValue();
float y = frameDict->valueForKey("y")->floatValue();
float w = frameDict->valueForKey("width")->floatValue();
float h = frameDict->valueForKey("height")->floatValue();
float ox = frameDict->valueForKey("offsetX")->floatValue();
float oy = frameDict->valueForKey("offsetY")->floatValue();
int ow = frameDict->valueForKey("originalWidth")->intValue();
int oh = frameDict->valueForKey("originalHeight")->intValue();
// check ow/oh
if(!ow || !oh)
{
CCLOGWARN("cocos2d: WARNING: originalWidth/Height not found on the CCSpriteFrame. AnchorPoint won't work as expected. Regenrate the .plist");
}
// abs ow/oh
ow = abs(ow);
oh = abs(oh);
// create frame
spriteFrame = new CCSpriteFrame();
spriteFrame->initWithTexture(pobTexture,
CCRectMake(x, y, w, h),
false,
CCPointMake(ox, oy),
CCSizeMake((float)ow, (float)oh)
);
}
else if(format == 1 || format == 2)
{
CCRect frame = CCRectFromString(frameDict->valueForKey("frame")->getCString());
bool rotated = false;
// rotation
if (format == 2)
{
rotated = frameDict->valueForKey("rotated")->boolValue();
}
CCPoint offset = CCPointFromString(frameDict->valueForKey("offset")->getCString());
CCSize sourceSize = CCSizeFromString(frameDict->valueForKey("sourceSize")->getCString());
// create frame
spriteFrame = new CCSpriteFrame();
spriteFrame->initWithTexture(pobTexture,
frame,
rotated,
offset,
sourceSize
);
}
else if (format == 3)
{
// get values
CCSize spriteSize = CCSizeFromString(frameDict->valueForKey("spriteSize")->getCString());
CCPoint spriteOffset = CCPointFromString(frameDict->valueForKey("spriteOffset")->getCString());
CCSize spriteSourceSize = CCSizeFromString(frameDict->valueForKey("spriteSourceSize")->getCString());
CCRect textureRect = CCRectFromString(frameDict->valueForKey("textureRect")->getCString());
bool textureRotated = frameDict->valueForKey("textureRotated")->boolValue();
// get aliases
CCArray* aliases = (CCArray*) (frameDict->objectForKey("aliases"));
CCString * frameKey = new CCString(spriteFrameName);
CCObject* pObj = NULL;
CCARRAY_FOREACH(aliases, pObj)
{
std::string oneAlias = ((CCString*)pObj)->getCString();
if (m_pSpriteFramesAliases->objectForKey(oneAlias.c_str()))
{
CCLOGWARN("cocos2d: WARNING: an alias with name %s already exists", oneAlias.c_str());
}
m_pSpriteFramesAliases->setObject(frameKey, oneAlias.c_str());
}
frameKey->release();
// create frame
spriteFrame = new CCSpriteFrame();
spriteFrame->initWithTexture(pobTexture,
CCRectMake(textureRect.origin.x, textureRect.origin.y, spriteSize.width, spriteSize.height),
textureRotated,
spriteOffset,
spriteSourceSize);
}
// add sprite frame
m_pSpriteFrames->setObject(spriteFrame, spriteFrameName);
spriteFrame->release();
}
}
void CCSpriteFrameCache::addSpriteFramesWithFile(const char *pszPlist, CCTexture2D *pobTexture)
{
std::string fullPath = CCFileUtils::sharedFileUtils()->fullPathForFilename(pszPlist);
CCDictionary *dict = CCDictionary::createWithContentsOfFileThreadSafe(fullPath.c_str());
addSpriteFramesWithDictionary(dict, pobTexture);
dict->release();
}
OK!事情明了了。cocos2d-x比cocos2d-iphone多做了一步校验。
CCSpriteFrame* spriteFrame = (CCSpriteFrame*)m_pSpriteFrames->objectForKey(spriteFrameName);
if (spriteFrame)
{
continue;
}
然后,我将c++版本的plist加载顺序调整一下。搞定。
多说一句,一个png就不应该同时添加到两个plist中。