问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

易语言 http读文件() 怎么读出来的网页源码是乱码呀

发布网友 发布时间:2022-04-30 21:22

我来回答

6个回答

懂视网 时间:2022-05-01 01:43

- (BOOL)open {
 if (_db) {
 return YES;
 }
 
 int err = sqlite3_open([self sqlitePath], (sqlite3**)&_db );
 if(err != SQLITE_OK) {
 NSLog(@"error opening!: %d", err);
 return NO;
 }
 // 若_maxBusyRetryTimeInterval大于0,那么就调用setMaxBusyRetryTimeInterval:函数
 // setMaxBusyRetryTimeInterval:函数主要是调用sqlite3_busy_handler来处理其他线程已经在操作数据库的情况,默认_maxBusyRetryTimeInterval为2。
 // 具体该参数有什么用,下面在FMDBDatabaseBusyHandler函数中会详解。
 if (_maxBusyRetryTimeInterval > 0.0) {
 [self setMaxBusyRetryTimeInterval:_maxBusyRetryTimeInterval];
 }
 
 return YES;
}

- (void)setMaxBusyRetryTimeInterval:(NSTimeInterval)timeout {
 
 _maxBusyRetryTimeInterval = timeout;
 
 if (!_db) {
 return;
 }
 // 处理的handler设置为FMDBDatabaseBusyHandler这个函数
 if (timeout > 0) {
 sqlite3_busy_handler(_db, &FMDBDatabaseBusyHandler, (__bridge void *)(self));
 }
 else {
 // 不使用任何busy handler处理
 sqlite3_busy_handler(_db, nil, nil);
 }
}

这里需要提一下sqlite3_busy_handler这个函数:

int sqlite3_busy_handler(sqlite3*, int(*)(void*,int), void*);

第一个参数是告知哪个数据库需要设置busy handler。

第二个参数是其实就是回调函数(busy handler)了,当你调用该回调函数时,需传递给它的一个void*的参数的拷贝,也即sqlite3_busy_handler的第三个参数;另一个需要传给回调函数的int参数是表示这次锁事件,该回调函数被调用的次数。如果回调函数返回0时,将不再尝试再次访问数据库而返回SQLITE_BUSY或者SQLITE_IOERR_BLOCKED。如果回调函数返回非0, 将会不断尝试操作数据库。

总结:程序运行过程中,如果有其他进程或者线程在读写数据库,那么sqlite3_busy_handler会不断调用回调函数,直到其他进程或者线程释放锁。获得锁之后,不会再调用回调函数,从而向下执行,进行数据库操作。该函数是在获取不到锁的时候,以执行回调函数的次数来进行延迟,等待其他进程或者线程操作数据库结束,从而获得锁操作数据库。

大家也看出来了,sqlite3_busy_handler函数的关键就是这个回调函数了,此处作者定义的是一个名叫FMDBDatabaseBusyHandler的函数作为其busy handler。

// 注意:appledoc(生成文档的软件)中,对于有具体实现的C函数,比如下面这个函数,
// 是有bug的。所以你在生成文档时,忽略.m文件。

// 该函数就是简单调用sqlite3_sleep来挂起进程
static int FMDBDatabaseBusyHandler(void *f, int count) {
 FMDatabase *self = (__bridge FMDatabase*)f;
 // 如果count为0,表示的第一次执行回调函数
 // 初始化self->_startBusyRetryTime,供后面计算delta使用
 if (count == 0) {
 self->_startBusyRetryTime = [NSDate timeIntervalSinceReferenceDate];
 return 1;
 }
 // 使用delta变量控制执行回调函数的次数,每次挂起50~100ms
 // 所以maxBusyRetryTimeInterval的作用就在这体现出来了
 // 当挂起的时长大于maxBusyRetryTimeInterval,就返回0,并停止执行该回调函数了
 NSTimeInterval delta = [NSDate timeIntervalSinceReferenceDate] - (self->_startBusyRetryTime);
 
 if (delta < [self maxBusyRetryTimeInterval]) {
  // 使用sqlite3_sleep每次当前线程挂起50~100ms
 int requestedSleepInMillseconds = (int) arc4random_uniform(50) + 50;
 int actualSleepInMilliseconds = sqlite3_sleep(requestedSleepInMillseconds); 
 // 如果实际挂起的时长与想要挂起的时长不一致,可能是因为构建SQLite时没将HAVE_USLEEP置为1
 if (actualSleepInMilliseconds != requestedSleepInMillseconds) {
  NSLog(@"WARNING: Requested sleep of %i milliseconds, but SQLite returned %i. Maybe SQLite wasn‘t built with HAVE_USLEEP=1?", requestedSleepInMillseconds, actualSleepInMilliseconds);
 }
 return 1;
 }
 
 return 0;
}

2.3 - [FMDatabase executeQuery:withArgumentsInArray:orDictionary:orVAList:](重点)

为什么不讲 - [FMDatabase executeQuery:]?因为- [FMDatabase executeQuery:]等等类似的函数,最终都是对- [FMDatabase executeQuery:withArgumentsInArray:orDictionary:orVAList:]的简单封装。该函数比较关键,主要是针对查询的sql语句。

- (FMResultSet *)executeQuery:(NSString *)sql withArgumentsInArray:(NSArray*)arrayArgs orDictionary:(NSDictionary *)dictionaryArgs orVAList:(va_list)args {
 // 判断当前是否存在数据库以供操作
 if (![self databaseExists]) {
 return 0x00;
 }
 // 如果当前线程已经在使用数据库了,那就输出正在使用的警告
 if (_isExecutingStatement) {
 [self warnInUse];
 return 0x00;
 }
 
 _isExecutingStatement = YES;
 
 int rc   = 0x00; 
 sqlite3_stmt *pStmt = 0x00; // sqlite的prepared语句类型
 FMStatement *statement = 0x00; // 对sqlite3_stmt的简单封装,在实际应用中,你不应直接操作FMStatement对象
 FMResultSet *rs  = 0x00; // FMResultSet对象是用来获取最终查询结果的
 // 需要追踪sql执行状态的话,输出执行状态
 if (_traceExecution && sql) {
 NSLog(@"%@ executeQuery: %@", self, sql);
 }
 // 调用sql语句之前,首先要将sql字符串预处理一下,转化为SQLite可用的prepared语句(预处理语句)
 // 使用sqlite3_prepare_v2来生成sql对应的prepare语句(即pStmt)代价很大
 // 所以建议使用缓存机制来减少对sqlite3_prepare_v2的使用
 if (_shouldCacheStatements) {
 // 获取到缓存中的prepared语句
 statement = [self cachedStatementForQuery:sql];
 pStmt = statement ? [statement statement] : 0x00;
 // prepared语句可以被重置(调用sqlite3_reset函数),然后可以重新绑定参数以便重新执行。
 [statement reset];
 }
 // 如果缓存中没有sql对应的prepared语句,那么只能使用sqlite3_prepare_v2函数进行预处理
 if (!pStmt) {
 
 rc = sqlite3_prepare_v2(_db, [sql UTF8String], -1, &pStmt, 0);
 // 如果生成prepared语句出错,那么就根据是否需要打印错误信息(_logsErrors)以及是否遇到错误直接中止程序执行(_crashOnErrors)来执行出错处理。
 // 最后调用sqlite3_finalize函数释放所有的内部资源和sqlite3_stmt数据结构,有效删除prepared语句。
 if (SQLITE_OK != rc) {
  if (_logsErrors) {
  NSLog(@"DB Error: %d "%@"", [self lastErrorCode], [self lastErrorMessage]);
  NSLog(@"DB Query: %@", sql);
  NSLog(@"DB Path: %@", _databasePath);
  }
  
  if (_crashOnErrors) {
  NSAssert(false, @"DB Error: %d "%@"", [self lastErrorCode], [self lastErrorMessage]);
  // abort()函数表示中止程序执行,直接从调用的地方跳出。
  abort();
  }
  
  sqlite3_finalize(pStmt);
  _isExecutingStatement = NO;
  return nil;
 }
 }
 
 id obj;
 int idx = 0;
 // 获取到pStmt中需要绑定的参数个数
 int queryCount = sqlite3_bind_parameter_count(pStmt); // pointed out by Dominic Yu (thanks!)
 
 // 举一个使用dictionaryArgs的例子
 
/**
 NSMutableDictionary 
*dictionaryArgs = [NSMutableDictionary dictionary]; [dictionaryArgs setObject:@"Text1" forKey:@"a"]; [db executeQuery:@"select * from namedparamcounttest where a = :a" withParameterDictionary:dictionaryArgs]; // 注意类似:AAA前面有冒号的就是参数 // 其他的参数形式如:"?", "?NNN", ":AAA", "$AAA", 或 "@AAA" */
 if (dictionaryArgs) {
 
 for (NSString *dictionaryKey in [dictionaryArgs allKeys]) {
  
  // 在每个dictionaryKey之前加上冒号,比如上面的a -> :a,方便获取参数在prepared语句中的索引
  NSString *parameterName = [[NSString alloc] initWithFormat:@":%@", dictionaryKey];
  // 查看执行状况
  if (_traceExecution) {
  NSLog(@"%@ = %@", parameterName, [dictionaryArgs objectForKey:dictionaryKey]);
  }
  
  // 在prepared语句中查找对应parameterName的参数索引值namedIdx
  int namedIdx = sqlite3_bind_parameter_index(pStmt, [parameterName UTF8String]);
  
  FMDBRelease(parameterName);
  // 可以利用索引namedIdx获取对应参数,再使用bindObject:函数将dictionaryArgs保存的value绑定给对应参数
  if (namedIdx > 0) {
  [self bindObject:[dictionaryArgs objectForKey:dictionaryKey] toColumn:namedIdx inStatement:pStmt];
  // 使用这个idx来判断sql中的所有参数值是否都绑定上了
  idx++;
  }
  else {
  NSLog(@"Could not find index for %@", dictionaryKey);
  }
 }
 }
 else {
 
 while (idx < queryCount) {
  // 使用arrayArgs的例子
  /**
  [db executeQuery:@"insert into testOneHundredTwelvePointTwo values (?, ?)" withArgumentsInArray:[NSArray arrayWithObjects:@"one", [NSNumber numberWithInteger:2], nil]];
  */
  if (arrayArgs && idx < (int)[arrayArgs count]) {
  obj = [arrayArgs objectAtIndex:(NSUInteger)idx];
  }
 // 使用args的例子,使用args其实就是调用- (FMResultSet *)executeQuery:(NSString*)sql, ...;
 /**
  FMResultSet *rs = [db executeQuery:@"select rowid,* from test where a = ?", @"hi‘"];
  */
  else if (args) {
  obj = va_arg(args, id);
  }
  else {
  break;
  }
  
  if (_traceExecution) {
  if ([obj isKindOfClass:[NSData class]]) {
   NSLog(@"data: %ld bytes", (unsigned long)[(NSData*)obj length]);
  }
  else {
   NSLog(@"obj: %@", obj);
  }
  }
  
  idx++;
  // 绑定参数值
  [self bindObject:obj toColumn:idx inStatement:pStmt];
 }
 }
 // 如果绑定的参数数目不对,认为出错,并释放资源
 if (idx != queryCount) {
 NSLog(@"Error: the bind count is not correct for the # of variables (executeQuery)");
 sqlite3_finalize(pStmt);
 _isExecutingStatement = NO;
 return nil;
 }
 
 FMDBRetain(statement); // to balance the release below
 // statement不为空,进行缓存
 if (!statement) {
 statement = [[FMStatement alloc] init];
 [statement setStatement:pStmt];
 // 使用sql作为key来缓存statement(即sql对应的prepare语句)
 if (_shouldCacheStatements && sql) {
  [self setCachedStatement:statement forQuery:sql];
 }
 }
 
 // 根据statement和self(FMDatabase对象)构建一个FMResultSet对象,此函数中仅仅是构建该对象,还没使用next等函数获取查询结果
 // 注意FMResultSet中含有以下成员(除了最后一个,其他成员均在此处初始化过了)
 /**
 @interface FMResultSet : NSObject {
  FMDatabase  *_parentDB; // 表示该对象查询的数据库,主要是为了能在FMResultSet自己的函数中索引到正在操作的FMDatabase对象
  FMStatement  *_statement; // prepared语句
 
  NSString  *_query; // 对应的sql查询语句
  NSMutableDictionary *_columnNameToIndexMap; 
 }
 */
 rs = [FMResultSet resultSetWithStatement:statement usingParentDatabase:self];
 [rs setQuery:sql];
 // 将此时的FMResultSet对象添加_openResultSets,主要是为了调试
 NSValue *openResultSet = [NSValue valueWithNonretainedObject:rs];
 [_openResultSets addObject:openResultSet];
 // 并设置statement的使用数目useCount加1,暂时不清楚此成员有何作用,感觉也是用于调试
 [statement setUseCount:[statement useCount] + 1];
 
 FMDBRelease(statement);
 // 生成statement的操作已经结束
 _isExecutingStatement = NO;
 
 return rs;
}

2.4 - [FMResultSet nextWithError:]

- [FMResultSet next]函数其实就是对nextWithError:的简单封装。作用就是从我们上一步open中获取到的FMResultSet对象中读取查询后结果的每一行,交给用户自己处理。读取每一行的方法(即next)其实就是封装了sqlite3_step函数。而nextWithError:主要封装了对sqlite3_step函数返回结果的处理。

int sqlite3_step(sqlite3_stmt*);

sqlite3_prepare函数将SQL命令字符串解析并转换为一系列的命令字节码,这些字节码最终被传送到SQlite3的虚拟数据库引擎(VDBE: Virtual Database Engine)中执行,完成这项工作的是sqlite3_step函数。比如一个SELECT查询操作,sqlite3_step函数的每次调用都会返回结果集中的其中一行,直到再没有有效数据行了。每次调用sqlite3_step函数如果返回SQLITE_ROW,代表获得了有效数据行,可以通过sqlite3_column函数提取某列的值。如果调用sqlite3_step函数返回SQLITE_DONE,则代表prepared语句已经执行到终点了,没有有效数据了。很多命令第一次调用sqlite3_step函数就会返回SQLITE_DONE,因为这些SQL命令不会返回数据。对于INSERT,UPDATE,DELETE命令,会返回它们所修改的行号——一个单行单列的值。

// 返回YES表示从数据库中获取到了下一行数据
- (BOOL)nextWithError:(NSError **)outErr {
 // 尝试步进到下一行
 int rc = sqlite3_step([_statement statement]);
 
 // 对返回结果rc进行处理

 /**
 SQLITE_BUSY 数据库文件有锁
 SQLITE_LOCKED 数据库中的某张表有锁
 SQLITE_DONE sqlite3_step()执行完毕
 SQLITE_ROW sqlite3_step()获取到下一行数据
 SQLITE_ERROR 一般用于没有特别指定错误码的错误,就是说函数在执行过程中发生了错误,但无法知道错误发生的原因。
 SQLITE_MISUSE 没有正确使用SQLite接口,比如一条语句在sqlite3_step函数执行之后,没有被重置之前,再次给其绑定参数,这时bind函数就会返回SQLITE_MISUSE。
 */ 
 if (SQLITE_BUSY == rc || SQLITE_LOCKED == rc) {
 NSLog(@"%s:%d Database busy (%@)", __FUNCTION__, __LINE__, [_parentDB databasePath]);
 NSLog(@"Database busy");
 if (outErr) {
  // lastError使用sqlite3_errcode获取到错误码,封装成NSError对象返回
  *outErr = [_parentDB lastError];
 }
 }
 else if (SQLITE_DONE == rc || SQLITE_ROW == rc) {
 // all is well, let‘s return.
 }
 else if (SQLITE_ERROR == rc) {
 // sqliteHandle就是获取到对应FMDatabase对象,然后使用sqlite3_errmsg来获取错误码的字符串
 NSLog(@"Error calling sqlite3_step (%d: %s) rs", rc, sqlite3_errmsg([_parentDB sqliteHandle]));
 if (outErr) {
  *outErr = [_parentDB lastError];
 }
 }
 else if (SQLITE_MISUSE == rc) {
 // uh oh.
 NSLog(@"Error calling sqlite3_step (%d: %s) rs", rc, sqlite3_errmsg([_parentDB sqliteHandle]));
 if (outErr) {
  if (_parentDB) {
  *outErr = [_parentDB lastError];
  }
  else {
  // 如果next和nextWithError函数是在当前的FMResultSet关闭之后调用的
  // 这时输出的错误信息应该是parentDB不存在
  NSDictionary* errorMessage = [NSDictionary dictionaryWithObject:@"parentDB does not exist" forKey:NSLocalizedDescriptionKey];
  *outErr = [NSError errorWithDomain:@"FMDatabase" code:SQLITE_MISUSE userInfo:errorMessage];
  }
  
 }
 }
 else {
 // wtf?
 NSLog(@"Unknown error calling sqlite3_step (%d: %s) rs", rc, sqlite3_errmsg([_parentDB sqliteHandle]));
 if (outErr) {
  *outErr = [_parentDB lastError];
 }
 }
 
 // 如果不是读取下一行数据,那么就关闭数据库
 if (rc != SQLITE_ROW) {
 [self close];
 }
 
 return (rc == SQLITE_ROW);
}

2.5 - [FMDatabase close]

与open函数成对调用。主要还是封装了sqlite_close函数。

- (BOOL)close {
 // 清除缓存的prepared语句,下面会详解
 [self clearCachedStatements];
 // 关闭所有打开的FMResultSet对象,目前看来这个_openResultSets大概也是用来调试的 
 [self closeOpenResultSets];
 
 if (!_db) {
 return YES;
 }
 
 int rc;
 BOOL retry;
 BOOL triedFinalizingOpenStatements = NO;
 
 do {
 retry = NO;
 // 调用sqlite3_close来尝试关闭数据库
 rc = sqlite3_close(_db);
//如果当前数据库上锁,那么就先尝试重新关闭(置retry为YES) // 同时还尝试释放数据库中的prepared语句资源
 if (SQLITE_BUSY == rc || SQLITE_LOCKED == rc) {
  if (!triedFinalizingOpenStatements) {
  triedFinalizingOpenStatements = YES;
  sqlite3_stmt *pStmt;
// sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt
)表示从数据库pDb中对应的pStmt语句开始一个个往下找出相应prepared语句,如果pStmt为nil,那么就从pDb的第一个prepared语句开始。
  // 此处迭代找到数据库中所有prepared语句,释放其资源。
  while ((pStmt = sqlite3_next_stmt(_db, nil)) !=0) {
   NSLog(@"Closing leaked statement");
   sqlite3_finalize(pStmt);
   retry = YES;
  }
  }
 }
 // 关闭出错,输出错误码
 else if (SQLITE_OK != rc) {
  NSLog(@"error closing!: %d", rc);
 }
 }
 while (retry);
 
 _db = nil;
 return YES;
}

// _cachedStatements是用来缓存prepared语句的,所以清空_cachedStatements就是将每个缓存的prepared语句释放
// 具体实现就是使用下面那个close函数,close函数中调用了sqlite_finalize函数释放资源
- (void)clearCachedStatements {
 
 for (NSMutableSet *statements in [_cachedStatements objectEnumerator]) {
 // makeObjectsPerformSelector会并发执行同一件事,所以效率比for循环一个个执行要快很多
 [statements makeObjectsPerformSelector:@selector(close)];
 }
 
 [_cachedStatements removeAllObjects];
}
// 注意:此为FMResultSet的close函数
- (void)close {
 if (_statement) {
 sqlite3_finalize(_statement);
 _statement = 0x00;
 }
 
 _inUse = NO;
}

// 清除_openResultSets
- (void)closeOpenResultSets {
 //Copy the set so we don‘t get mutation errors
 NSSet *openSetCopy = FMDBReturnAutoreleased([_openResultSets copy]);
 // 迭代关闭_openResultSets中的FMResultSet对象
 for (NSValue *rsInWrappedInATastyValueMeal in openSetCopy) {
 FMResultSet *rs = (FMResultSet *)[rsInWrappedInATastyValueMeal pointerValue];
 // 清除FMResultSet的操作
 [rs setParentDB:nil];
 [rs close];
 
 [_openResultSets removeObject:rsInWrappedInATastyValueMeal];
 }
}

3. 总结

本文结合一个基本的FMDB使用案例,介绍了FMDB基本的运作流程和内部实现。总的来说,FMDB就是对SQLite的封装,所以学习FMDB根本还是在学习SQLite数据库操作。

4. 参考文章


  • SQLITE和多线程

  • sqlite3之sqlite3_busy_handler使用详解

  • SQlite数据库的C编程接口(三) 预处理语句(Prepared Statements) ——《Using SQlite》读书笔记 .

  • SQlite数据库的C编程接口(六) 返回值和错误码(Result Codes and Error Codes) ——《Using SQlite》读书笔记

  • 【原】FMDB源码阅读(一)

    标签:

    热心网友 时间:2022-04-30 22:51

    原因是:操作错误导致的,具体解决方法步骤如下:

    1.首先打开电脑,在电脑中运行“易语言”主程序,弹出“新建项目对话框”,选择“Windows窗口程序”,点击“确定”,进入“Windows窗口编程界面”。

    2.接下来,拖放一个标签组件、两个编辑框组件、一个按钮组件和一个分组框组件。将它们放置在适当的位置,并将窗口的宽度和高度设置为适当的大小。确保窗户简洁美观。

    3.界面调整后,将窗口标题、标签标题、框标题和按钮标题分组到相应内容中,并根据规范对编辑框和按钮组件进行命名。准备编写程序代码。

    4.下一步是编写代码,在“_button_source_wasclicked”事件子例程中,编写如下代码[editbox_websource]。内容=文本(HTTP读取文件(编辑框_url)。内容)。

    5.代码正确编写后,进入调试阶段。按“F5”快捷键运行程序,我们以百度体验网站为例,点击“source”按钮,等待程序执行。

    6.从web源代码编辑框中获得反馈结果分析,如果源代码出现凌乱的代码通常是一个编码问题。此时,您需要进行代码转换,您可以看到正常的代码。然后,您需要对代码做一些小的修改。

    7、重测程序,从web源编辑框反馈的结果可以看出web源的阅读是正确的。

    热心网友 时间:2022-05-01 00:09

    易语言 http读文件() 读出来的网页源码是乱码的原因是操作错误导致的,具体解决方法步骤如下:

    1、首先打开计算机,在计算机内运行“易语言”主程序,弹出“新建工程对话框”选择“Windows窗口程序”然后点击“确定”按钮,进入“Windows窗口程序设计界面”。

    2、接下来,拖放标签组件一个、编辑框组件两个、按钮组件一个及分组框组件一个。将它们放置到合适的位置并将窗口的宽高设置到适当的大小。以确保窗口的简洁美观。

    3、待界面调整完毕之后,将窗口标题、标签标题、分组框标题及按钮标题修改成相应内容,并且将编辑框、按钮组件规范命名。为编写程序代码做准备。

    4、接下来就是编写代码了,在“_按钮_获取源码_被单击”事件子程序下,编写如下代码【 编辑框_网页源码.内容 = 到文本 (HTTP读文件 (编辑框_网址.内容)) 】。

    5、待代码编写无误后,进入调试阶段。按下“F5”快捷键运行程序,网址我们以百度经验的网址为例,然后点击“获取源码”按钮,等待程序执行。

    6、从网页源码编辑框得到的反馈结果分析,如果源码中出现乱码通常是编码方式的问题。这个时候,需要进行转码,就能看到正常的代码了。那么,代码也需要做小的改动。

    7、重新测试程序,从网页源码编辑框的反馈结果可以看出,这次读取的网页源码是正确的。

    热心网友 时间:2022-05-01 01:44

    这时因为http读文件返回的是gb2312编码数据,而网页中使用的是uft-8编码,可以使用精易模块中的url编码命令将返回的数据进行解码。

    1、新建易语言程序,在窗口中添加按钮,然后设置按钮的标题,双击按钮添加按钮点击事件:

    2、使用http读文件命令读取网页,这里以读取百度首页为例,然后将返回的数据输出调试出来,可以发现这时读取的源码是乱码:

    3、点击窗口左侧的“程序”按钮,然后将精易模块引入到易语言中:

    4、使用“编码_URL解码”命令对返回的数据进行解码,这个命令的第二个参数填写为真则表示返回的数据是uft-8编码格式,这时返回的数据就被解码到中文了:

    热心网友 时间:2022-05-01 03:35

    你要进行编码转换的呀。。。

    我写的源码

    =====================

    .版本 2

    .支持库 internet

    .支持库 iconv

    .支持库 spec


    .子程序 _按钮1_被单击

    .局部变量 字节集, 字节集

    .局部变量 转换句柄, 整数型


    字节集 = HTTP读文件 (“http://www.baidu.com/”)

    转换句柄 = 编码转换_打开 (#编码_UTF_8, #编码_GBK)

    字节集 = 编码转换_转换 (转换句柄, 字节集, )

    编码转换_关闭(转换句柄)

    调试输出 (到文本 (字节集))

    -----------------以下是百度主页的源码(转换后)

    ---------------------------你刚才的地址

    热心网友 时间:2022-05-01 05:43

    你需要转码 中文字符才能显示追问转码要自己编写代码吗

    追答.版本 2

    .子程序 彗星URL解码_UTF8, 文本型, 公开, 返回已解码的URL
    .参数 Bin_URL, 文本型, , 欲解码的文本
    .局部变量 循环容器, 整数型
    .局部变量 Len, 整数型
    .局部变量 HEX, 文本型
    .局部变量 目标, 文本型
    .局部变量 H, 整数型
    .局部变量 L, 整数型

    Len = 取文本长度 (Bin_URL)
    循环容器 = 1
    HEX = “0123456789ABCDEF”
    .判断循环首 (循环容器 ≤ Len)
    .判断开始 (取文本中间 (Bin_URL, 循环容器, 1) ≠ “%”)
    目标 = 目标 + 取文本中间 (Bin_URL, 循环容器, 1)
    .默认
    循环容器 = 循环容器 + 1
    H = 寻找文本 (HEX, 到大写 (取文本中间 (Bin_URL, 循环容器, 1)), , 假) - 1
    循环容器 = 循环容器 + 1
    L = 寻找文本 (HEX, 到大写 (取文本中间 (Bin_URL, 循环容器, 1)), , 假) - 1
    目标 = 目标 + 字符 (H × 16 + L)
    .判断结束
    循环容器 = 循环容器 + 1
    .判断循环尾 ()
    返回 (Utf8转ansi (到字节集 (目标)))

    声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
    我爱的人或美女子在古文中用什么词代替? 急 企业文化,经营宗旨 三星I9300手机刷机进不到英文界面,进不到绿色机器人界面?怎么办?_百度... I9300刷机没成功,然后发现内存也不够了,大婶们,该怎么解决啊,想重新... 三星i9300删除软件开机画面定格要刷机吗 高仿联通定制版i9300,刷机失败,开机黑屏,挖煤模式机器人倒地,出现红 ... 禾香板是什么样子的 禾香板和颗粒板的的区别是什么 摊煎饼怎么和面 丝瓜栽培技术的要点丝瓜怎么施肥比较好 电信手机4G网变成了2G网? 在word中如何输入几的几次方?例如2的2次方如何输 请问word文档里如何打几次方那些呢? 在Word文档中,几次方怎么弄? Word 2003里怎么打几的次方?急,谢谢 WORD里幂次数怎么写 用word 怎么打多少幂次方。我的是07版本word. word中如何设置几次幂 怎样用word打次方数? 成年公鸭和母鸭的区别 烤鸭的是用公鸭来做好还是用母鸭来做的好? 吃公鸭与母鸭有区别吗? 母鸭和公鸭的区别? 一般吃公鸭还是母鸭 鸭子公的好吃 母的好吃? 这时节鸭子吃公还是吃母好 胃溃疡、胃糜烂傻傻分不清楚,到底怎么辨别呢? 吃公鸭好还是吃母鸭好 哪个有营养 疣状胃炎怎样治疗最好? 疣状胃炎 公鸭怎么做好吃煲汤 华为手机有没有其他方法隐藏应用图标? 快手那些说3D音乐是怎么做的? 朵朵丰胸胸贴真的有效吗? 淘宝里面的美人字大大大胸贴真的能丰胸吗 那些丰胸乳贴加精油真的有用吗 有谁用过朵朵神速大丰胸乳贴吗效果好不好啊? 快手上那些将dj音乐变的立体 低音很强 用的什么软件 谁知道除了快手上3D环绕音乐视频是怎么做的?这样的歌词炫彩的 用丰胸乳贴,结果胸上长了好几个痘痘,胸也不见得大,还能继续用&#65533; 译青春能量胸贴丰胸吗 美人痣丰胸乳贴用了安全吗? 深v致命诱惑丰胸贴是真的假的? 男人能用丰胸乳贴吗 乳液,乳膏和乳贴那个丰胸效果好? 如何提高团队管理能力8 怎么提高团队管理水平 情人节用什么方法和女友开房 为什么谈恋爱的时候要开房? 肉炒笋瓜的做法,肉炒笋瓜怎么做好吃,肉炒笋瓜 情侣开房,房费俩人应该怎么分摊比较好?