标签 输入 下的文章

getline() 提供了一种更灵活的方法,可以在不破坏系统的情况下将用户数据读入程序。

在 C 语言中读取字符串是一件非常危险的事情。当读取用户输入时,程序员可能会尝试使用 C 标准库中的 gets 函数。它的用法非常简单:

char *gets(char *string);

gets() 从标准输入读取数据,然后将结果存储在一个字符串变量中。它会返回一个指向字符串的指针,如果没有读取到内容,返回 NULL 值。

举一个简单的例子,我们可能会问用户一个问题,然后将结果读入字符串中:

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

int main()
{
  char city[10]; // 例如 "Chicago"

  // 这种方法很糟糕 .. 不要使用 gets

  puts("Where do you live?");
  gets(city);

  printf("<%s> is length %ld\n", city, strlen(city));

  return 0;
}

输入一个相对较短的值就可以:

Where do you live?
Chicago
<Chicago> is length 7

然而,gets() 函数非常简单,它会天真地读取数据,直到它认为用户完成为止。但是它不会检查字符串是否足够容纳用户的输入。输入一个非常长的值会导致 gets() 存储的数据超出字符串变量长度,从而导致覆盖其他部分内存。

Where do you live?
Llanfairpwllgwyngyllgogerychwyrndrobwllllantysiliogogogoch
<Llanfairpwllgwyngyllgogerychwyrndrobwllllantysiliogogogoch> is length 58
Segmentation fault (core dumped)

最好的情况是,覆盖部分只会破坏程序。最坏的情况是,这会引入一个严重的安全漏洞,恶意用户可以通过你的程序将任意数据插入计算机的内存中。

这就是为什么在程序中使用 gets() 函数是危险的。使用 gets(),你无法控制程序尝试从用户读取多少数据,这通常会导致缓冲区溢出。

安全的方法

fgets() 函数历来是安全读取字符串的推荐方法。此版本的 gets() 提供了一个安全检查,通过仅读取作为函数参数传递的特定数量的字符:

char *fgets(char *string, int size, FILE *stream);

fgets() 函数会从文件指针读取数据,然后将数据存储到字符串变量中,但最多只能达到 size 指定的长度。我们可以更新示例程序来测试这一点,使用 fgets() 而不是 gets()

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

int main()
{
    char city[10]; // 例如 "Chicago"

    puts("Where do you live?");

    // fgets 虽好但是并不完美
    fgets(city, 10, stdin);

    printf("<%s> is length %ld\n", city, strlen(city));

    return 0;
}

如果编译运行,你可以在提示符后输入任意长的城市名称。但是,程序只会读取 size = 10 数据存储到字符串变量中。因为 C 语言在字符串末尾会添加一个空(\0)字符,这意味着 fgets() 只会读取 9 个字符到字符串中。

Where do you live?
Minneapolis
<Minneapol> is length 9

虽然这肯定比 fgets() 读取用户输入更安全,但代价是如果用户输入过长,它会“切断”用户输入。

新的安全方法

更灵活的解决方案是,如果用户输入的数据比变量可能容纳的数据多,则允许字符串读取函数为字符串分配更多内存。根据需要调整字符串变量大小,确保程序始终有足够的空间来存储用户输入。

getline() 函数正是这样。它从输入流读取输入,例如键盘或文件,然后将数据存储在字符串变量中。但与 fgets()gets() 不同,getline() 使用 realloc() 调整字符串大小,确保有足够的内存来存储完整输入。

ssize_t getline(char **pstring, size_t *size, FILE *stream);

getline() 实际上是一个名为 getdelim() 的类似函数的装饰器,它会读取数据一直到特殊分隔符停止。本例中,getline() 使用换行符(\n)作为分隔符,因为当从键盘或文件读取用户输入时,数据行由换行符分隔。

结果证明这是一种更安全的方法读取任意数据,一次一行。要使用 getline(),首先定义一个字符串指针并将其设置为 NULL ,表示还没有预留内存,再定义一个 size_t 类型的“字符串大小” 的变量,并给它一个零值。当你调用 getline() 时,你需要传入字符串和字符串大小变量的指针,以及从何处读取数据。对于示例程序,我们可以从标准输入中读取:

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

int main()
{
  char *string = NULL;
  size_t size = 0;
  ssize_t chars_read;

  // 使用 getline 读取长字符串

  puts("Enter a really long string:");

  chars_read = getline(&string, &size, stdin);
  printf("getline returned %ld\n", chars_read);

  // 检查错误

  if (chars_read < 0) {
    puts("couldn't read the input");
    free(string);
    return 1;
  }

  // 打印字符串

  printf("<%s> is length %ld\n", string, strlen(string));

  // 释放字符串使用的内存

  free(string);

  return 0;
}

使用 getline() 读取数据时,它将根据需要自动为字符串变量重新分配内存。当函数读取一行的所有数据时,它通过指针更新字符串的大小,并返回读取的字符数,包括分隔符。

Enter a really long string:
Supercalifragilisticexpialidocious
getline returned 35
<Supercalifragilisticexpialidocious
> is length 35

注意,字符串包含分隔符。对于 getline(),分隔符是换行符,这就是为什么输出中有换行符的原因。 如果你不想在字符串值中使用分隔符,可以使用另一个函数将字符串中的分隔符更改为空字符。

通过 getline(),程序员可以安全地避免 C 编程的一个常见陷阱:你永远无法知道用户可能会输入哪些数据。这就是为什么使用 gets() 不安全,而 fgets() 又太笨拙的原因。相反,getline() 提供了一种更灵活的方法,可以在不破坏系统的情况下将用户数据读入程序。

(题图:MJ/4b23132f-8916-42ae-b2da-06fd2812bea8)


via: https://opensource.com/article/22/5/safely-read-user-input-getline

作者:Jim Hall 选题:lkxed 译者:MjSeven 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

学习 Java 如何外理数据的读与写。

 title=

当你写一个程序时,你的应用程序可能需要读取和写入存储在用户计算机上的文件。这在你想加载或存储配置选项,你需要创建日志文件,或你的用户想要保存工作以待后用的情况下是很常见的。每种语言处理这项任务的方式都有所不同。本文演示了如何用 Java 处理数据文件。

安装 Java

不管你的计算机是什么平台,你都可以从 AdoptOpenJDK 安装 Java。这个网站提供安全和开源的 Java 构建。在 Linux 上,你的软件库中也可能找到 AdoptOpenJDK 的构建。

我建议你使用最新的长期支持(LTS)版本。最新的非 LTS 版本对希望尝试最新 Java 功能的开发者来说是最好的,但它很可能超过大多数用户所安装的版本 —— 要么是系统上默认安装的,要么是以前为其他 Java 应用安装的。使用 LTS 版本可以确保你与大多数用户所安装的版本保持一致。

一旦你安装好了 Java,就可以打开你最喜欢的文本编辑器并准备开始写代码了。你可能还想要研究一下 Java 集成开发环境。BlueJ 是新程序员的理想选择,而 Eclipse 和 Netbeans 对中级和有经验的编码者更友好。

利用 Java 读取文件

Java 使用 File 类来加载文件。

这个例子创建了一个叫 Ingest 的类来读取文件中数据。当你要在 Java 中打开一个文件时,你创建了一个 Scanner 对象,它可以逐行扫描你提供的文件。事实上,Scanner 与文本编辑器中的光标是相同的概念,这样你可以用 Scanner 的一些方法(如 nextLine)来控制这个“光标”以进行读写。

import java.io.File;
import java.util.Scanner;
import java.io.FileNotFoundException;

public class Ingest {
  public static void main(String[] args) {
   
      try {
          File myFile = new File("example.txt");
          Scanner myScanner = new Scanner(myFile);
          while (myScanner.hasNextLine()) {
              String line = myScanner.nextLine();
              System.out.println(line);
          }
          myScanner.close();
      } catch (FileNotFoundException ex) {
          ex.printStackTrace();  
      } //try
    } //main
} //class

这段代码首先在假设存在一个名为 example.txt 的文件的情况下创建了变量 myfile。如果该文件不存在,Java 就会“抛出一个异常”(如它所说的,这意味着它在你试图做的事情中发现了一个错误),这个异常是被非常特定的 FileNotFoundException 类所“捕获”。事实上,有一个专门的类来处理这个明确的错误,这说明这个错误是多么常见。

接下来,它创建了一个 Scanner 并将文件加载到其中。我把它叫做 myScanner,以区别于它的通用类模板。接着,一个 while 循环将 myScanner 逐行送入文件中,只要 存在 下一行。这就是 hasNextLine 方法的作用:它检测“光标”之后是否还有数据。你可以通过在文本编辑器中打开一个文件来模拟这个过程:你的光标从文件的第一行开始,你可以用键盘控制光标来向下扫描文件,直到你走完了所有的行。

while 循环创建了一个变量 line,并将文件当前行的数据分配给它。然后将 line 的内容打印出来以提供反馈。一个更有用的程序可能会解析每一行的内容,从而提取它所包含的任何重要数据。

在这个过程结束时,关闭 myScanner 对象。

运行代码

将你的代码保存到 Ingest.java 文件(这是一个 Java 惯例,将类名的首字母大写,并以类名来命名相应的文件)。如果你试图运行这个简单的应用程序,你可能会接收到一个错误信息,这是因为还没有 example.txt 文件供应用程序加载:

$ java ./Ingest.java
java.io.FileNotFoundException:
example.txt (No such file or directory)

正好可以编写一个将数据写入文件的 Java 应用程序,多么完美的时机!

利用 Java 将数据写入文件

无论你是存储用户使用你的应用程序创建的数据,还是仅仅存储关于用户在应用程序中做了什么的元数据(例如,游戏保存或最近播放的歌曲),有很多很好的理由来存储数据供以后使用。在 Java 中,这是通过 FileWriter 类实现的,这次先打开一个文件,向其中写入数据,然后关闭该文件。

import java.io.FileWriter;
import java.io.IOException;

public class Exgest {
  public static void main(String[] args) {
    try {
        FileWriter myFileWriter = new FileWriter("example.txt", true);
        myFileWriter.write("Hello world\n");
        myFileWriter.close();
    } catch (IOException ex) {
        System.out.println(ex);
    } // try
  } // main
}

这个类的逻辑和流程与读取文件类似。但它不是一个 Scanner,而是以一个文件的名字为参数创建的一个 FileWriter 对象。FileWriter 语句末尾的 true 标志告诉 FileWriter 将文本 追加 到文件的末尾。要覆盖一个文件的内容,请移除 true 标志。

`FileWriter myFileWriter = new FileWriter("example.txt", true);`

因为我在向文件中写入纯文本,所以我在写入文件的数据(Hello world)的结尾处手动添加了换行符(\n)。

试试代码

将这段代码保存到 Exgest.java 文件,遵循 Java 的惯例,使文件名为与类名相匹配。

既然你已经掌握了用 Java 创建和读取数据的方法,你可以按相反的顺序尝试运行你的新应用程序。

$ java ./Exgest.java
$ java ./Ingest.java
Hello world
$

因为程序是把数据追加到文件末尾,所以你可以重复执行你的应用程序以多次写入数据,只要你想把更多的数据添加到你的文件中。

$ java ./Exgest.java
$ java ./Exgest.java
$ java ./Exgest.java
$ java ./Ingest.java
Hello world
Hello world
Hello world
$

Java 和数据

你不会经常向文件中写入原始文本;事实上,你可能会使用一个其它的类库以写入特定的格式。例如,你可能使用 XML 类库来写复杂的数据,使用 INI 或 YAML 类库来写配置文件,或者使用各种专门类库来写二进制格式,如图像或音频。

更完整的信息,请参阅 OpenJDK 文档


via: https://opensource.com/article/21/3/io-java

作者:Seth Kenlon 选题:lujun9972 译者:piaoshi 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

如果,你像我这样,是个对统计数据有着狂热癖好的人,那么你必须在你的计算机上安装这个小应用:WhatPulse

此软件会追踪用户的击键、鼠标点击以及使用的带宽和系统开机时间。用户可以周期性地,或者手动上传击键的数量到服务器上,这称之为“脉动”。

用户可以看到他们在所有加入该程序的人的领先选手排行板的所处位置,并且与他们自己国家的人作比较。用户也可以加入团队,在团队中他们可以和有着相同爱好的人作对比(去吧,Linux用户们!!)。

软件分为免费的基础版和高级版,在基础版中你可以查看并检查所有的基本统计数据,而在高级版中你可以看到更多。

该软件可用于Linux,Windows和Mac。

在线注册

第一步,你必须在WhatPulse网站注册帐号,或者也可以在你第一次启动WhatPulse客户端时出现的实用向导中创建帐号,以用于上传自己的统计数据(你也可以使用Facebook的帐号登录)。

你会被提示需要登录,登录之后,你必须找到你的计算机名,这是因为你可以通过该帐号登录到多台计算机,而它们的数据都会上传到同一统计帐号。一旦你登入后,一个小小的W将出现在你的系统托盘中,那就对了,你已搞定!

在Linux上安装WhatPulse

官方网站在下载页提供了一个通用版本的.tar.gz归档压缩包(用于32位和64位)和一个debian包。

就我个人而言,我已经在我的Mint Qiana上安装了debian包,在我的Arch LinuxAur包一点问题都没有。

如果你想要使用通用版本安装,请记住:WhatPulse需要几个库文件。最主要的是QT,因为WhatPulse构建于QT平台。下面列出了软件安装需求:

  • libQtCore
  • libQtWebKit
  • libqt4-sql
  • libqt4-sql-sqlite
  • openssl-devel (libssl-dev)
  • libQtScript

输入统计数据

客户端需要设置相应的权限,以读取键盘/鼠标输入。运行包含的交互脚本.sh来设置这些权限。

网络统计数据

要启用网络测量,你也需要libpcap包来允许WhatPulse挂钩到网络通信。如果WhatPulse找不到libpcap,它会运行,但不会显示任何网络统计数据。

使用应用程序

默认情况下,WhatPulse会在登入图形会话后自动启动。点击系统托盘上的W图标,你将进入总览标签页,这里显示你机器上收集到的所有不同信息的鸟瞰图。例如,安装在你PC上的Linux版本、处理器型号、RAM、GPU、总点击次数、击键和带宽使用。点击这些信息下面的‘Pulse’,它将会上传这些收集到的数据到主服务器上。

也可以选择自动‘Pulse’数据到服务器的时间,如每50.000点击,或者1GB下载量。

要了解深度详情,你可以切换到每个类目的附属标签。例如,Input标签展示给你的是注册后一段时间内的击键的数量和点击次数。时间周期分为每日、每周、每月、每年以及全时。‘all’设置将显示程序安装以来的数据。

在击键下面,你会找到键盘点击热图,它简单地使用冷暖色显示选定周期内各个键的使用状况,如上述截图所示。在图的下面,应用显示了选定周期内记录的点击总量。

在Network标签下,可以查看到日常互联网使用情况。应用程序可以监控所有网络设备的带宽使用量,甚至也可以给你展示按国家分布的带宽使用情况。再次提醒,你可以使用顶部右边的箭头按钮浏览可用的数据。

在网站上,你会看到与客户端上相同的所有统计数据。

免责声明:上面的WhatPulse网站链接包含了我的参考链接,注册时可以使用该链接,这会让我的帐号在某天升级到高级帐号。


via: http://linuxaria.com/recensioni/check-how-much-do-you-type-with-whatpulse-on-linux

作者:linuxari 译者:GOLinux 校对:wxy

本文由 LCTT 原创翻译,Linux中国 荣誉推出