战魂小筑

讨论群:309800774 知乎关注:http://zhihu.com/people/sunicdavy 开源项目:https://github.com/davyxu

   :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  257 随笔 :: 0 文章 :: 506 评论 :: 0 Trackbacks

#

先说下我的工程目录

ProjectName\

src\

  core\

  share\

  proj.android\

    jni\

    …

sdk\

  protobuf-2.4.1\

    src\

    …

从Google code下载protobuf-2.4.1源码包, 解压, 在protobuf-2.4.1目录下添加Android.mk, 内容如下

LOCAL_PATH := $(call my-dir)
 
include $(CLEAR_VARS)
 
LOCAL_MODULE := protobuf-2.4.1
 
LOCAL_SRC_FILES := \
src/google/protobuf/io/coded_stream.cc                \
src/google/protobuf/io/printer.cc                     \
src/google/protobuf/io/gzip_stream.cc                 \
src/google/protobuf/io/tokenizer.cc                   \
src/google/protobuf/io/zero_copy_stream.cc            \
src/google/protobuf/io/zero_copy_stream_impl.cc       \
src/google/protobuf/io/zero_copy_stream_impl_lite.cc  \
src/google/protobuf/stubs/common.cc                   \
src/google/protobuf/stubs/once.cc                     \
src/google/protobuf/stubs/structurally_valid.cc       \
src/google/protobuf/stubs/strutil.cc                  \
src/google/protobuf/stubs/substitute.cc               \
src/google/protobuf/compiler/importer.cc              \
src/google/protobuf/compiler/parser.cc                \
src/google/protobuf/descriptor.cc                     \
src/google/protobuf/descriptor.pb.cc                  \
src/google/protobuf/descriptor_database.cc            \
src/google/protobuf/dynamic_message.cc                \
src/google/protobuf/extension_set.cc                  \
src/google/protobuf/extension_set_heavy.cc            \
src/google/protobuf/generated_message_reflection.cc   \
src/google/protobuf/generated_message_util.cc         \
src/google/protobuf/message.cc                        \
src/google/protobuf/message_lite.cc                   \
src/google/protobuf/reflection_ops.cc                 \
src/google/protobuf/repeated_field.cc                 \
src/google/protobuf/service.cc                        \
src/google/protobuf/text_format.cc                    \
src/google/protobuf/unknown_field_set.cc              \
src/google/protobuf/wire_format.cc                    \
src/google/protobuf/wire_format_lite.cc               \
 
 
LOCAL_C_INCLUDES := $(LOCAL_PATH) \
                    $(LOCAL_PATH)/src
                   
 
include $(BUILD_STATIC_LIBRARY)

此时编译会报config.h找不到的错误, 这个文件在vsproject目录有, 但只是VC编译使用,  这篇文章说需要手动创建, 但实际上, Linux下可以通过config系统自动生成的, 但是Android平台下,不使用cygwin时, 就需要自己手动创建config.h, 内容如下

/*
    This make file is only for android ONLY, modified by Davy Xu June 17, 2013
    Cause android platform can't use linux config system when cygwin envirement is not available
*/
 
/* the location of <hash_set> */
#define HASH_SET_H <ext/hash_set>
#define HASH_MAP_H <ext/hash_map>
#define HASH_NAMESPACE __gnu_cxx
 
/* define if the compiler has hash_map */
//#define HAVE_HASH_MAP 1
 
/* define if the compiler has hash_set */
//#define HAVE_HASH_SET 1
 
#define HAVE_PTHREAD

剩下的事情就简单了, 在你的工程Android.mk里添加protobuf的引用

例如:

LOCAL_WHOLE_STATIC_LIBRARIES += protobuf-2.4.1

$(call import-module,protobuf-2.4.1)

还要在NDK_MODULE_PATH中增加搜索路径D:\Develop\ProjectName\sdk\

注意, 这里protobuf-2.4.1名称必须与sdk下的文件夹名, LOCAL_MODULE中的名称保持一致, 否则搜索不到

posted @ 2013-06-17 11:40 战魂小筑 阅读(5380) | 评论 (0)编辑 收藏

最近将cocos2dx的程序移植到Android上, 某阶段突然发现开始闪退. 日志方式跟了很久, 发现有内存被修改. 因为不能像VC那样有内存断点, 只有靠日志继续跟踪, 绕了很久, 终于发现一个问题

CCApplication::sharedApplication()->run(); 在Windows下除了初始化回调外, 还有Windows平台特殊的消息循环. 既然是循环, 这个run函数会一直阻塞到程序退出, 因此我自然的在run后添加自己的资源卸载

换到Android上呢CCApplication::sharedApplication()->run();的实现变了. 由于Android上没有Windows的消息循环, 所有事件都是通过java方式的事件通知. 因此CCApplication::sharedApplication()->run();变成了非阻塞, 可是我在run后添加了资源卸载. 结果导致系统刚初始化就卸载了资源, 内存直接不可用, 导致后面cocos2dx的API部分使用无问题, 而自己引擎的API调用闪退.

cocos2dx的这个run函数命名有严重问题.. 被坑了好久, 还一直怀疑NDK内存管理是否有特殊之处, 殊不知..

posted @ 2013-06-14 17:15 战魂小筑 阅读(9695) | 评论 (5)编辑 收藏

本文整个部署过程无需下载及安装使用Cygwin环境, 以下部署过程需要用到的程序及版本

请注意下载对应你系统的版本, 64位系统请保证后文全系使用64位程序, 以免遇到不必要的麻烦

1.JDK&JRE       JAVA运行时及开发包

2.ADT               是Eclipse的一个插件,这一步是为了管理安卓开发库

http://developer.android.com/sdk/index.html

作为新手, 请下载ADT Bundle For Windows, 这个版本已经包含

ADK(安卓开发包), CDT(Eclipse的C/C++开发插件)及对应的Eclipse, 可以避免第一次部署出现的各种烦心!

3.NDK              只有ADT已经可以运行普通的Andriod程序,但是如果需要编译C/C++程序, 还需要NDK

http://developer.android.com/tools/sdk/ndk/index.html

4. cocos2dx 2.0.4版本

 

准备SDK API

下载好ADT后解压, 有如下目录

eclipse\      <- 开发环境

sdk\           <- Andriod SDK

SDK Manager.exe     <-- Android开发包管理器, 由于Andriod版本较多, 所以此管理器可以方便开发者选择部署目标机器

打开SDK Manager在Android 2.2(API 8)里的 SDK Platform, Google APIs前打勾, 点击右下角的Instal packages

如果感觉下载速度慢, 可以移步这里http://my.oschina.net/heguangdong/blog/17443, 选择Andriod离线下载

这里是下载链接

http://dl-ssl.google.com/android/repository/google_apis-8_r02.zip

http://dl-ssl.google.com/android/repository/android-2.2_r02-windows.zip

https://dl-ssl.google.com/android/repository/usb_driver_r04-windows.zip

把android开头的文件解压到platforms目录下

把goole_apis开头的文件解压到add-ons目录下

把usb_driver_r03-windows.zip解压到usb_driver目录下。

Eclipse导入工程

打开Eclipse

导入Cocos2dx例子工程:

Eclipse中File->New->Other...选择Andriod Project from Existing Code

在Import Projects的Root Directory中导入D:\Develop\RevWar\sdk\cocos2d-2.0-x-2.0.4\samples\HelloCpp\proj.android\

注意, 不要选中 Copy project into workspace, 否则路径编乱很难编译成功

 

导入cocos2dx的java框架

在src目录中new package, 输入org.cocos2dx.lib, 在org.cocos2dx.lib的package中点Import-> FileSystem

选中目录D:\Develop\RevWar\sdk\cocos2d-2.0-x-2.0.4\cocos2dx\platform\android\java\src\org\cocos2dx\lib\, 点选所有java文件

工程Properties->Builder->New->Program

在Main标签中填写

填写NDK编译命令行 D:\Develop\android-ndk-r8e\ndk-build.cmd

点击Browser Workspace选中当前工程,出现${workspace_loc:/HelloCpp}

切换到Environment标签中填写

新建NDK_MODULE_PATH 填写D:\Develop\RevWar\sdk\cocos2d-2.0-x-2.0.4\;D:\Develop\RevWar\sdk\cocos2d-2.0-x-2.0.4\cocos2dx\platform\third_party\android\prebuilt\

修改cocos2dx的Android.mk, diff如下

@@ -153,6 +153,7 @@

LOCAL_WHOLE_STATIC_LIBRARIES += cocos_jpeg_static

LOCAL_WHOLE_STATIC_LIBRARIES += cocos_libxml2_static

LOCAL_WHOLE_STATIC_LIBRARIES += cocos_libtiff_static

+LOCAL_WHOLE_STATIC_LIBRARIES += cocosdenshion_static

# define the macro to compile through support/zip_support/ioapi.c              

LOCAL_CFLAGS := -DUSE_FILE32API

@@ -164,3 +165,4 @@

$(call import-module,libpng)

$(call import-module,libxml2)

$(call import-module,libtiff)

+$(call import-module,CocosDenshion/android)

F&Q

andriod-8问题

修改D:\Develop\RevWar\sdk\cocos2d-2.0-x-2.0.4cocos2dx\platform\android\java\project.properties中的target=android-8改成你需要的版本

resources.ap_ does not exist

assert目录中有资源出问题, 排查即可

例如: cocos2d-2.0-x-2.0.4\samples\TestCpp\proj.android\assets\Images\*.pvr.gz

启动Android模拟器时的Failed to allocate memory: 8问题

调整内存值,请求内存太大导致

api版本过低导致JAVA Symbol未定义问题

setEGLContextClientVersion undefined

api8(andriod 2.2)后的版本, 才支持openGL es 2.0

自己做工程遇到的问题D:\Develop\RevWar\sdk\cocos2d-2.0-x-2.0.4\/cocos2dx/platform/android/jni/JniHelper.h:28:18: fatal error: string: No such file or directory

将cocos2dx例子中的Application.mk拷过来, 修改下内部名称即可

调试请尽量使用真机, 模拟器速度很慢

小米2默认只能管理文件, 无法用adb 连接, 因此需要安装驱动, USB驱动直接在插入电脑后的虚拟盘里找.. 这个太坑了..

保证每次都能部署最新的程序

请执行每次Clean, Build project, Debug.  真机上在需要时, 会弹出安装...

Android启动日志

带有ADT的Eclipse中有一个logcat窗口, 里面有系统及程序本身的日志, 可以做过滤,方便检查问题. 如需自己打日志, 可以使用cocos2dx中的LOGD宏来做, 原型是__android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__)

 

Remark

添加assert后, F5刷新后再编译
NDK build时,默认从工程的jni目录开始

Andriod.mk的import 原则$(call import-module,模块名) 这里的模块名必须与目录名, 模块make file中的名称报纸一致

参考文章

http://www.cnblogs.com/ybgame/archive/2012/06/07/2540693.html

发文时, Andriod Studio已经发布了一段时间, 虽然是测试版, 但将代表未来更方便的Andriod发布工具

posted @ 2013-06-09 17:55 战魂小筑 阅读(18980) | 评论 (0)编辑 收藏

   最近开始弄cocos2dx, 图片需要整合成POT的优化纹理, 使用texturePacker来做
下载http://www.codeandweb.com/texturepacker/download
工具本身不是免费的, 但是可以通过申请获得免费的Licence, 点这里
条件是有一个自己的博客, 并且从事游戏/软件/网页方面的开发, 且近期有5篇文章发表
作者特别强调,微博不等于博客

填写好邮箱地址,要不了几个小时就可以获取到序列号
posted @ 2013-06-05 15:44 战魂小筑 阅读(2491) | 评论 (1)编辑 收藏

https://code.google.com/p/protoc-gen-lua/ 下载网易兄弟写的lua的protobuf插件(网易都把pb给弄完了,as3的也是他们写的..)

 

编译python版的protobuf模块

https://code.google.com/p/protobuf/downloads/list 下载官方的原生版本protobuf, 这里发文时使用的是2.4.1版本

编译出protoc执行文件, 放一份在protobuf-2.4.1\src\下

下载python2.7版本, 在protobuf-2.4.1\python下运行python setup.py install(如果找不到python请给python绝对路径)

这一步, python会下一个蛋( 真的是一个python的egg文件 ), 然后编译出python版本的protobuf模块放置在python下

 

制作protoc-gen-lua的批处理

放一份protoc在protoc-gen-lua的plugin目录

编写批处理:protoc-gen-lua.bat

@python "%~dp0protoc-gen-lua"

 

协议目录生成脚本

在你需要放置协议的目录编写如下批处理

buildproto.bat

rd /S /Q .\%1%
"..\..\src\protoc-gen-lua\plugin\protoc.exe" --plugin=protoc-gen-lua="..\..\src\protoc-gen-lua\plugin\protoc-gen-lua.bat" --lua_out=. %1%.proto

注意protoc.exe及protoc-gen-lua.bat的路径符合你的路径

再编写要编译的proto协议的批处理generate.bat

call buildproto.bat loginsvc

执行generate.bat后, 将会编译同目录下的loginsvc.proto,输出loginsvc_pb.lua

 

编译链接lua的pb库

将protoc-gen-lua\protobuf\目录拷贝到之前的协议目录

将其下的pb.c链入你的工程, 注意VS2010的VC下需要修改源码

1.将 #include <endian.h>修改为

#ifndef _WIN32
     #include <endian.h>
     #endif

避免在windows下缺失文件报错.

2. 调整struct_unpack函数前几行为

static int struct_unpack(lua_State *L)
{
    uint8_t format = luaL_checkinteger(L, 1);
    size_t len;
    const uint8_t* buffer = (uint8_t*)luaL_checklstring(L, 2, &len);
    size_t pos = luaL_checkinteger(L, 3);
    uint8_t out[8];   

    buffer += pos;

避免VS2010的VC编译器过于标准, 严格要求C风格函数变量前置声明

在lua_State声明后添加如下代码

extern "C" { int luaopen_pb (lua_State *L);}   // 注意防在命名空间外的全局声明

    luaopen_pb( L );   // 直接注入全局pb, 避免动态加载pb.dll造成的一系列跨平台问题

 

lua中使用pb

local loginsvc_pb = require “loginsvc_pb”
 
local REQ = loginsvc_pb.CheckVersionREQ()
local Data = REQ:SerializeToString( )
 
local ACK = loginsvc_pb.CheckVersionACK()
ACK:ParseFromString( Data )

 

.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }

我的工程目录

script\
        protobuf\
            buildproto.bat
            generate.bat
            loginsvc_pb.lua
            loginsvc.proto
        Main.lua
    src\
        protoc-gen-lua\
            example\
            plugin\
            protobuf\

posted @ 2013-04-24 15:44 战魂小筑 阅读(13405) | 评论 (4)编辑 收藏

为了降低模块间的耦合, 很多系统使用事件派发机制, 接收方无需知道派发者是谁.在Qt中,这个系统被称作Slot&Signal, 需要配合moc代码生成机制, 但是系统本身是线程安全的.

这里我们讨论的是lua的事件派发机制, 我将此写成lua模块, 方便配合cocos2dx进行逻辑处理

 

local Global = _G
local package = _G.package
local setmetatable = _G.setmetatable
local assert = _G.assert
local table = _G.table
local pairs = _G.pairs
local ipairs = _G.ipairs
 
 
module "Core.EventDispatcher"
 
--[[
数据层次
 
["EventName1"] =
{
    ["_StaticFunc"] = { Func1, Func2 },
    
    [Object1] = { Func1, Func2 },
    [Object2] = { Func1, Func2 },
},
 
["EventName2"] =
{
    ...
}
 
]]
 
-- 默认调用函数
local function PreInvoke( EventName, Func, Object, UserData, ... )
    
    if Object then
        Func( Object, EventName, ... )
    else
        Func( EventName, ... )
    end
 
end
 
function New( )    
    
    local NewObj = setmetatable( {}, { __index = package.loaded["Core.EventDispatcher"] } )
    
    -- 对象成员初始化
    NewObj.mPreInvokeFunc = PreInvoke
    NewObj.mEventTable = {}
    
    return NewObj
end
 
-- 添加
function Add( Self, EventName, Func, Object, UserData )
 
    assert( Func )
 
    Self.mEventTable[ EventName ] = Self.mEventTable[ EventName ] or {}
    
    local Event = Self.mEventTable[ EventName ]
    
    if not Object then
        Object = "_StaticFunc"
    end
    
    Event[Object] = Event[Object] or {}
    local ObjectEvent = Event[Object]
 
    ObjectEvent[Func] = UserData or true
    
end
 
-- 设置调用前回调
function SetDispatchHook( Self, HookFunc )
    
    Self.mPreInvokeFunc = HookFunc
end
 
 
-- 派发
function Dispatch( Self, EventName, ... )
 
    assert( EventName )
    
    local Event = Self.mEventTable[ EventName ]
    
    for Object,ObjectFunc in pairs( Event ) do
        
        if Object == "_StaticFunc" then
                
            for Func, UserData in pairs( ObjectFunc ) do
                Self.mPreInvokeFunc( EventName, Func, nil, UserData, ... )    
            end
            
        else
        
            for Func, UserData in pairs( ObjectFunc ) do
                Self.mPreInvokeFunc( EventName, Func, Object, UserData, ... )
            end
        
        end
 
    end
 
end
 
-- 回调是否存在
function Exist( Self, EventName )
 
    assert( EventName )
    
    local Event = Self.mEventTable[ EventName ]
    
    if not Event then
        return false
    end
    
    -- 需要遍历下map, 可能有事件名存在, 但是没有任何回调的
    for Object,ObjectFunc in pairs( Event ) do
    
        for Func, _ in pairs( ObjectFunc ) do
            -- 居然有一个
            return true
        end
    
    end
    
    
    return false
    
end
 
-- 清除
function Remove( Self, EventName, Func, Object )
    
    assert( Func )
    
    local Event = Self.mEventTable[ EventName ]
    
    if not Event then
        return
    end
    
    if not Object then
        Object = "_StaticFunc"
    end
    
    
    local ObjectEvent = Event[Object]
    
    if not ObjectEvent then
        return
    end
    
    ObjectEvent[Func] = nil
 
        
end
 
-- 清除对象的所有回调
function RemoveObjectAllFunc( Self, EventName, Object )
 
    assert( Object )
    
    local Event = Self.mEventTable[ EventName ]
    
    if not Event then
        return
    end
    
    Event[Object] = nil
 
end
 

这里注意下, 我是将EventDispatcher.lua放置在Core目录下, 因此需要使用require “Core.EventDispatcher”进行调用

使用用例

 

    local EventDispatcher = require 'Core.EventDispatcher'
 
    local E = EventDispatcher.New()
 
 
    E:Add( "a", function( a, b )   print( a, b ) end )
 
    local Func = function( a )   print( a ) end 
    E:Add( "a", Func )
 
 
    E:Dispatch("a", 1, 2 )
    print( E:Exist("a"), E:Exist("b"))
 
    E:Remove("a", Func )
 
    E:Dispatch("a", 1, 2 )
    print( E:Exist("a"), E:Exist("b"))
posted @ 2013-04-24 15:19 战魂小筑 阅读(6987) | 评论 (0)编辑 收藏

Linux上跑服务器如果遇到程序崩溃是一件很苦恼的事情, 再碰到重现很难的BUG, 估计只能通过传统的排查方法进行.

在编写本文前, 笔者使用过诸如libunwind等库进行错误时堆栈打印, 但是其本身由于需要引用第三方库, 使用还是稍微麻烦.

经过Google后, 居然找到一篇好文, 其通过捕获SIGSEGV信号, 并迫使程序进入gdb调试阶段, 利用gdb强大的调试功能可以进行各种错误跟踪, 此法已与Windows下程序崩溃后弹出VC调试几乎接近.

我在此文基础上, 扩展了其通用性及便利性

1. 使用gdb的 -ex参数, 在挂接程序后, 执行bt指令打出程序堆栈

2. 将信息重定向到自定义的文件,在多进程都需要进行后台输出时带来更大的灵活性, 同时也解决了gdb只能在前台调试的问题

代码如下

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>

void dump(int signo)
{
        char buf[1024];
        char cmd[1024];
        FILE *fh;

        snprintf(buf, sizeof(buf), "/proc/%d/cmdline", getpid());
        if(!(fh = fopen(buf, "r")))
                exit(0);
        if(!fgets(buf, sizeof(buf), fh))
                exit(0);
        fclose(fh);
        if(buf[strlen(buf) - 1] == '/n')
                buf[strlen(buf) - 1] = '/0';
        snprintf(cmd, sizeof(cmd), "gdb %s %d -ex=bt > ./a.txt", buf, getpid());
        system(cmd);

        exit(0);
}

在服务器开启时,添加 signal(SIGSEGV, &dump ); 进行信号处理挂接即可

 

 

引用: http://blog.csdn.net/kakaka2011/article/details/6597857  作者: kakaka2011

posted @ 2012-12-29 17:53 战魂小筑 阅读(9775) | 评论 (3)编辑 收藏

最近为服务器添加XMLSocket与Flash进行通信, 这种协议其实是一种以\0结尾的字符串协议, 为了让asio兼容此协议, 我从文档找到了async_read_until异步读取系列, 这个函数的原理时, 给定一个streambuf, 和一个分隔符, asio碰到分隔符时返回, 你可以从streambuf中读取需要的数据. 看似很简单, 我很快写好一个demo与Flash进行通信, 结果发现在一个echo逻辑速度很快时, 服务器居然乱包了, 网上查了下, 官方原文是这样的:

”After a successful async_read_until operation, the streambuf may contain additional data beyond the delimiter. An application will typically leave that data in the streambuf for a subsequent async_read_until operation to examine.”

意思是, streambuf中并不一定是到分隔符前的所有数据, 多余的数据可能一样会在streambuf中. 也就是说, 还需要自己再次处理一遍数据...

动手呗, async_read_until看似就是一个废柴, 底层已经费了很多CPU在逐字符与分隔符的匹配上, 抛上来的数据居然还是半成品.

代码如下, 测试通过, 但是实在很费解为啥非要再做一次..

          boost::asio::streambuf* SB = SBP.get();

            // 访问缓冲
            const char* Buffs = boost::asio::buffer_cast<const char*>( SB->data() );

            uint32 DataSize = 0;
            for ( uint32 i = 0; i < SB->size(); ++i )
            {
                const char DChar = Buffs[i];

                // 这里需要自己判断字符串内容, read_until的文档里这么说的
                if ( DChar == '\0' )
                {
                    DataSize = i;
                    break;
                }
            }

            if ( DataSize > 0 )
            {
                // 取成字符串
                std::string FullText( Buffs, DataSize );
                
                // 消费
                SB->consume( DataSize );                

                mWorkService->post(
                    boost::bind(&AsioSession::NotifyReadString,
                    shared_from_this(),
                    FullText )
                    );

            }
  另外, 为了保证输入性安全, 可以在streambuf构造时加一个最大一个读取量, 超过此量会返回报错, 避免了缓冲区被撑爆的危险
posted @ 2012-12-03 15:12 战魂小筑 阅读(11245) | 评论 (5)编辑 收藏

即便使用了Google SSL加密搜索, 由于Google需要对搜索结果进行点击跟踪,因此很容易被GFW重置连接. 使用以下方法可以避免此问题

在Chrome浏览器中输入chrome://net-internals/

在HSTS标签中输入www.google.com

点击add添加即可

posted @ 2012-09-17 23:22 战魂小筑 阅读(754) | 评论 (0)编辑 收藏

网上找了很多, 真正好用的代码不多, 自己研究了下,写下例子备份

 

Private Sub ConvFile(InputFile As String, OutputFile As String)
 
    Dim ReadStream As Object
    Set ReadStream = CreateObject("ADODB.Stream")
    
    Dim FileContent As String
    
    With ReadStream
        .Type = 2               'adTypeText
        .Charset = "UNICODE"
        .Open
        .LoadFromFile InputFile
        FileContent = .ReadText
        .Close
        
    End With
    
    Set ReadStream = Nothing
    
    
    
    Dim WriteStream As Object
    Set WriteStream = CreateObject("ADODB.Stream")
       
    
    With WriteStream
        .Type = 2               'adTypeText
        .Charset = "UTF-8"
        .Open
        .WriteText FileContent
        .SaveToFile OutputFile, 2  'adSaveCreateOverWrite
        
        .Flush
        .Close
        
    End With
    
    Set WriteStream = Nothing
 
    
End Sub

 

上半截是读取文件, 下半截是写入文件, 需要转换不同格式, 请自行更换

posted @ 2012-09-13 19:43 战魂小筑 阅读(8449) | 评论 (2)编辑 收藏

仅列出标题
共26页: First 4 5 6 7 8 9 10 11 12 Last