You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++Builder环境下Android设备二进制文件访问移植咨询

基于C++Builder将WinCE文件操作代码移植到Android的解决方案

核心问题解答

1. 能否继续使用C++标准文件访问函数?

可以。CBuilder的Clang编译器完全支持标准C库,包括<cstdio>中的fopen、fwrite、fread、fseek等函数,在Android平台下可直接沿用这些函数进行二进制文件操作。

2. 具体实现步骤

(1)适配文件路径与权限

Android文件系统权限规则与WinCE不同,需注意:

  • 私有存储:APP私有目录可直接访问,通过C++Builder的System.IOUtils获取路径,如TPath::GetDocumentsPath().c_str()
  • 外部存储:需在AndroidManifest.xml中添加READ_EXTERNAL_STORAGE/WRITE_EXTERNAL_STORAGE权限(Android 10+需适配分区存储规则,Android 11+可申请MANAGE_EXTERNAL_STORAGE权限)
  • 避免硬编码路径,优先使用系统API获取合法路径

(2)移除WinCE专属代码

原代码中的MultiByteToWideChar、ANSItoUnicode、TEXT宏等WinCE特有的编码转换和宏定义需删除,Android默认使用UTF-8编码,直接用char*路径即可。同时移除WinCE_DLL_API宏,改用标准C++函数声明。

(3)保留标准文件操作逻辑

fopen的打开模式(如"rb"、"r+b")、fseek的定位规则等与WinCE完全一致,无需修改。

3. 替代方案(若不想用标准函数)

如果需要更贴近Android原生的实现,可选择以下两种方式:

  • C++Builder跨平台API:使用System::Ioutils类,封装了TFile::ReadAllBytes()、TFile::WriteAllBytes()、TFile::Open()等跨平台文件操作方法
  • Android NDK POSIX API:使用open()、read()、write()、lseek()等底层系统调用,行为与标准C++函数类似

适配后的示例代码

以下是移除WinCE专属代码、适配Android环境的修改版本:

#include <cstdio>
#include <cstring>
#include <cstdlib>

// 定义返回值常量
#define APPEND 0
#define DATA_EXIST 1
#define DATA_FULL -1
#define NOT_FOUND 2

// 补充HASH_HEAD结构体定义(原代码未提供)
typedef struct {
    long MAX_REC;
    int TTLLEN;
    int ITMLEN;
    int HASHNUM;
    int tab_bottom;
    int inx_bottom;
    int HEADLEN;
    int start_byte;
} HASH_HEAD;

// 补充自定义字符串比较函数(原代码未提供)
int Str_cmp(const unsigned char* str1, const unsigned char* str2, int len)
{
    for (int i = 0; i < len; ++i) {
        if (str1[i] != str2[i]) {
            return str1[i] - str2[i];
        }
    }
    return 0;
}

int Hash2(char *DaTa_Fn, char *InDex_Fn, unsigned char *item, unsigned char *ttl_data, int *tab )
{
    unsigned char *cmp;
    int i, ret;
    int nill = -1, inx;
    long sum, stm_loc, x, k, MAX_INX;
    HASH_HEAD hash_head;

    ret = f_read(&hash_head, sizeof(hash_head), DaTa_Fn, 0L);
    if (!ret)
        return -2;  // 文件打开错误

    MAX_INX = hash_head.MAX_REC / 2;
    MAX_INX += hash_head.MAX_REC;

    cmp = (unsigned char *)malloc(hash_head.TTLLEN + 4);
    memset(cmp, '\x0', hash_head.TTLLEN + 4);

    stm_loc = sum = 0L;
    strcpy((char *)cmp, (char *)item);
    for (k = 1L, sum = 0L, i = 0; i < hash_head.ITMLEN; i++, k++)
        sum += (long)item[i] * k * k * (k % 10L + 1L);
    x = sum % hash_head.HASHNUM;
    stm_loc = x * 4L;
    sum = stm_loc;

    ret = f_read(&inx, 2, InDex_Fn, stm_loc);
    if (!ret)
        return -2;  // 文件打开错误

    if (inx == nill && *tab == nill)
    {
        if (hash_head.tab_bottom >= hash_head.MAX_REC || hash_head.inx_bottom >= MAX_INX)
        {
            free(cmp);
            return DATA_FULL;
        }

        f_write(&hash_head.tab_bottom, 2, InDex_Fn, stm_loc);

        stm_loc = (long)hash_head.tab_bottom * (long)hash_head.TTLLEN + (long)hash_head.HEADLEN;

        f_write(ttl_data, hash_head.TTLLEN, DaTa_Fn, stm_loc);

        *tab = hash_head.tab_bottom;
        hash_head.tab_bottom += 1;

        stm_loc = 0L;
        f_write(&hash_head.tab_bottom, 2, DaTa_Fn, stm_loc);

        free(cmp);
        return APPEND;
    }
    else if (inx == nill && *tab != nill)
    {
        free(cmp);
        return NOT_FOUND;
    }
    else // 冲突处理
    {
        while (1)
        {
            stm_loc = (long)inx * (long)hash_head.TTLLEN + (long)hash_head.HEADLEN;
            f_read(cmp, hash_head.TTLLEN, DaTa_Fn, stm_loc);

            i = Str_cmp(cmp + hash_head.start_byte, item, hash_head.ITMLEN);
            if (i == 0)
            {
                memcpy(ttl_data, cmp, hash_head.TTLLEN);
                *tab = inx;
                free(cmp);
                return DATA_EXIST;
            }
            else
            {
                sum += 2L;
                f_read(&inx, 2, InDex_Fn, sum);     // 获取下一个索引
                if (inx == nill && *tab != nill)
                {
                    free(cmp);
                    return NOT_FOUND;
                }
                if (inx == nill && *tab == nill)
                {
                    if (hash_head.tab_bottom >= hash_head.MAX_REC || hash_head.inx_bottom >= MAX_INX) // 无法追加
                    {
                        free(cmp);
                        return DATA_FULL;
                    }
                    f_write(&hash_head.inx_bottom, 2, InDex_Fn, sum);
                    stm_loc = (long)hash_head.inx_bottom * 4L;
                    sum = stm_loc;
                    f_write(&hash_head.tab_bottom, 2, InDex_Fn, sum);
                    sum += 2L;
                    f_write(&nill, 2, InDex_Fn, sum);

                    hash_head.inx_bottom += 1;
                    stm_loc = (long)hash_head.tab_bottom * (long)hash_head.TTLLEN + (long)hash_head.HEADLEN;

                    f_write(ttl_data, hash_head.TTLLEN, DaTa_Fn, stm_loc);

                    *tab = hash_head.tab_bottom;
                    hash_head.tab_bottom += 1;

                    f_write(&hash_head.tab_bottom, 2, DaTa_Fn, 0L);
                    f_write(&hash_head.inx_bottom, 2, DaTa_Fn, 2L);

                    free(cmp);
                    return APPEND;
                }
                else
                {
                    stm_loc = (long)inx * 4L;
                    sum = stm_loc;
                    f_read(&inx, 2, InDex_Fn, stm_loc);
                }
            }
        }
    }
}

/*--------F_read---------*/
int f_read(void *buffer, int count, char *fn, long fpos )
{
    int num;
    FILE *fp;

    if ((fp = fopen(fn, "rb")) == NULL)
    {
        return 0;
    }
    fseek(fp, fpos, SEEK_SET);
    num = fread(buffer, 1, count, fp);
    fclose(fp);

    return (num == count) ? 1 : 0;
}

/*--------F_append---------*/
int f_append(void *buffer, int count, char *fn )
{
    int num;
    FILE *fp;

    if ((fp = fopen(fn, "r+b")) == NULL)
    {
        // 文件不存在时尝试创建
        if ((fp = fopen(fn, "wb")) == NULL)
            return 0;
    }
    fseek(fp, 0, SEEK_END);
    num = fwrite(buffer, 1, count, fp);
    fclose(fp);
    return (num == count) ? 1 : 0;
}

/*--------F_write---------*/
int f_write(void  *buffer, int count, char *fn, long fpos )
{
    int num;
    FILE *fp;

    if ((fp = fopen(fn, "r+b")) == NULL)
    {
        return 0;
    }
    fseek(fp, fpos, SEEK_SET);
    num = fwrite(buffer, 1, count, fp);
    fclose(fp);
    return (num == count) ? 1 : 0;
}

注意事项

  1. 确保C++Builder项目目标平台选择Android,编译器使用Clang
  2. 测试时优先使用APP私有目录,避免权限问题
  3. 若原代码中HASH_HEAD结构体或其他辅助函数定义与示例不同,需根据实际情况调整

内容的提问来源于stack exchange,提问作者Sam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 16:45:32