【问题标题】:Comparing NSStrings before (and after) saving to sqlite database在保存到 sqlite 数据库之前(和之后)比较 NSStrings
【发布时间】:2010-11-17 17:41:09
【问题描述】:

在我的 Mac 和 iPhone 上,使用 Objective-c,我可以将 EURO 字符保存到 sqlite 数据库中。

在我存储之前,NSString 的长度是 1(或者应该是 2?)

在我从数据库中取回它后,NSString 的长度现在是 2(或者应该是 1?)

如何比较这两个 NSString? isEqualToString 不起作用。

(只要我坚持使用字符 0-127,读取/写入/比较就可以正常工作。)

这是一个大幅缩减的 sqlite READ 代码示例:

NSMutableString *s = [[[NSMutableString alloc] init] autorelease];
sqlite3_stmt *statement;
int i, numberOfColumns=0, columnType, numberOfRecords=0;
int anyInt;
double anyDouble;

char *anyText;

int prepareErrorNumber = sqlite3_prepare_v2(g_Db, [sqlCmd UTF8String], -1, &statement, nil);

if(prepareErrorNumber == SQLITE_OK)
{
    while(sqlite3_step(statement) == SQLITE_ROW)
    {
        numberOfRecords++;
        numberOfColumns = sqlite3_column_count(statement);

        columnType = sqlite3_column_type(statement, i);
            if(columnType == SQLITE_INTEGER) { anyInt    = sqlite3_column_int(statement, i);          [s appendFormat:@"%d", anyInt   ]; }
            if(columnType == SQLITE_TEXT   ) { anyText   = (char *)sqlite3_column_text(statement, i); [s appendFormat:@"%s", anyText  ]; }
            if(columnType == SQLITE_FLOAT  ) { anyDouble = sqlite3_column_double(statement, i);       [s appendFormat:@"%f", anyDouble]; }
        }

 ... etc...

【问题讨论】:

  • 示例代码展示了您存储和加载字符串的具体操作。
  • 您的代码处理编码不正确。发布相关位,我们可以提供帮助。 :) 特别是,我们对如何将字符串放入 sqlite 以及如何将其取出感兴趣。
  • 我会挖掘实际代码。 (它在我的工作计算机上。)所以你说我应该 NEVER 取回 2 个字节......如果我存储 1? (我认为如果字符在 0-127 范围之外,sqlite DID 会这样做。不是吗?) [dbResults length] 为 2 的事实绝对意味着我的 sqlite 读/写代码是错误的?) 我正在使用一些非常标准的 sqlite 代码,这些代码出现在整个网络上......它总是适用于除了 >127 个字符之外的所有内容。
  • 所以通常我应该能够在我从数据库保存/加载之前(和之后)看到 1 个字符(欧元)的长度?并且 isEqualToString 应该比较它们就好了?
  • 请记住,NSString 的长度不是字节数,而是字符数。如果在 NSString *mystring 中传递一个 EURO 字符需要两个字节,则 [mystring length] 将为 1。另一方面, strlen([mystring UTF8String]) 将是两个。

标签: iphone objective-c sqlite sdk nsstring


【解决方案1】:

您似乎正在尝试将插入添加为 NSString 并读取为 UTF8String。

写入时使用实例方法UTF8String,读取时使用类方法stringFromUTF8String:

【讨论】:

    【解决方案2】:

    很可能,您正在以错误的方式使用从读取中收集的信息创建NSString。这是一个将欧元符号写入数据库然后读回的完整示例:

    //clang -g so_sqlite3_nsstring.m -framework Foundation -lsqlite3 \
    //    -o so_sqlite3_nsstring
    #import <Foundation/Foundation.h>
    #import <sqlite3.h>
    
    #define DB_PATH "so_enc.db"
    
    enum {
      ALL_OK,
      CANT_OPEN,
      CANT_CREATE,
      CANT_INSERT,
      CANT_FIND,
    };
    
    struct ExecCBCtx {
      NSString **out_string;
    };
    int ExecCB(void *ctx, int col_count, char *col_text[], char *col_name[]);
    
    sqlite3 *DBCreate(void);
    void DBWrite(sqlite3 *db, NSString *text);
    NSString *DBRead(sqlite3 *db);
    
    int
    main(void) {
      id pool = [[NSAutoreleasePool alloc] init];
      sqlite3 *db = DBCreate();
    
      // Use universal character name for U+20AC "EURO SIGN".
      NSString *text = @"\u20AC";
      DBWrite(db, text);
    
      NSString *text2 = DBRead(db);
      (void)sqlite3_close(db);
    
      BOOL eq = [text isEqualToString:text2];
      NSLog(@"%@ = %@? %s", text, text2, eq? "YES" : "NO");
      [pool drain];
      return ALL_OK;
    }
    
    void
    DBOpen(sqlite3 **out_db)
    {
      sqlite3 *db = NULL;
      int rc = sqlite3_open(DB_PATH, out_db);
      if (rc) {
        fprintf(stderr, "sqlite3_open: %s\n", sqlite3_errmsg(*out_db));
        (void)sqlite3_close(*out_db);
        exit(CANT_OPEN);
      }
    }
    
    sqlite3 *
    DBCreate(void)
    {
      sqlite3 *db = NULL;
      DBOpen(&db);
    
      static const char CREATE_TABLE[] =
          "CREATE TABLE IF NOT EXISTS \"TEST\" (\"STRING\" char(9))";
      char *errmsg = NULL;
      int rc = sqlite3_exec(db, CREATE_TABLE, ExecCB, NULL, &errmsg);
      if (rc) {
        fprintf(stderr, "%s: %s\n", __func__, errmsg);
        sqlite3_free(errmsg);
        (void)sqlite3_close(db);
        exit(CANT_CREATE);
      }
      return db;
    }
    
    void
    DBWrite(sqlite3 *db, NSString *text)
    {
      static NSString *const WRITE_TABLE_FMT =
          @"INSERT INTO \"TEST\" VALUES (\"%@\")";
      NSString *writeText = [NSString stringWithFormat:WRITE_TABLE_FMT, text];
      const char *cmd = [writeText UTF8String];
    
      char *errmsg = NULL;
      int rc = sqlite3_exec(db, cmd, ExecCB, NULL, &errmsg);
      if (rc) {
        fprintf(stderr, "%s: %s\n", __func__, errmsg);
        sqlite3_free(errmsg);
        (void)sqlite3_close(db);
        exit(CANT_INSERT);
      }
    }
    
    NSString *
    DBRead(sqlite3 *db)
    {
      static const char READ_TABLE[] =
          "SELECT * FROM \"TEST\"";
    
      NSString *text = nil;
      struct ExecCBCtx ctx = {&text};
    
      char *errmsg = NULL;
      int rc = sqlite3_exec(db, READ_TABLE, ExecCB, &ctx, &errmsg);
      if (rc && rc != SQLITE_ABORT) {
        fprintf(stderr, "%s: %s\n", __func__, errmsg);
        sqlite3_free(errmsg);
        (void)sqlite3_close(db);
        exit(CANT_FIND);
      }
      sqlite3_free(errmsg);
      return text;
    }
    
    int
    ExecCB(void *ctx, int col_count, char *col_text[], char *col_name[])
    {
      //fprintf(stderr, "%s: %p - %d cols - %s - %s\n",
      //        __func__, ctx, col_count, col_text[0], col_name[0]);
      if (!ctx) return 0;
    
      struct ExecCBCtx *out = ctx;
      NSString **text = out->out_string;
      if (*text) return 1;
    
      *text = [NSString stringWithUTF8String:col_text[0]];
      return 0;
    }
    

    这是一个示例运行的输出:

    2010-11-17 14:34:05.436 so_sqlite3_nsstring[23536:903] € = €? YES
    

    【讨论】:

      【解决方案3】:

      => 写的时候使用实例方法UTF8String

      完成。 (我没有展示该代码,但它已经完成了。)

      => 和类方法 stringFromUTF8String: 读取时。

      我认为这是我需要修复的线路。
      但它会是什么样子?
      无论我如何重写它,我都无法让 stringFromUTF8String 工作。

      if(columnType == SQLITE_TEXT   ) 
      { 
          anyText = (char *)sqlite3_column_text(statement, i); 
         [s appendFormat:@"%s", anyText]; 
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-03-13
        • 1970-01-01
        • 2021-06-28
        • 1970-01-01
        • 2014-06-15
        相关资源
        最近更新 更多